michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=4 sw=4 et tw=80: michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "JavaScriptParent.h" michael@0: #include "mozilla/dom/ContentParent.h" michael@0: #include "nsJSUtils.h" michael@0: #include "jsfriendapi.h" michael@0: #include "jsproxy.h" michael@0: #include "jswrapper.h" michael@0: #include "HeapAPI.h" michael@0: #include "xpcprivate.h" michael@0: #include "mozilla/Casting.h" michael@0: michael@0: using namespace js; michael@0: using namespace JS; michael@0: using namespace mozilla; michael@0: using namespace mozilla::jsipc; michael@0: using namespace mozilla::dom; michael@0: michael@0: JavaScriptParent::JavaScriptParent() michael@0: : refcount_(1), michael@0: inactive_(false) michael@0: { michael@0: } michael@0: michael@0: static inline JavaScriptParent * michael@0: ParentOf(JSObject *obj) michael@0: { michael@0: MOZ_ASSERT(JavaScriptParent::IsCPOW(obj)); michael@0: return reinterpret_cast(GetProxyExtra(obj, 0).toPrivate()); michael@0: } michael@0: michael@0: ObjectId michael@0: JavaScriptParent::idOf(JSObject *obj) michael@0: { michael@0: MOZ_ASSERT(JavaScriptParent::IsCPOW(obj)); michael@0: michael@0: Value v = GetProxyExtra(obj, 1); michael@0: MOZ_ASSERT(v.isDouble()); michael@0: michael@0: ObjectId objId = BitwiseCast(v.toDouble()); michael@0: MOZ_ASSERT(findObject(objId) == obj); michael@0: MOZ_ASSERT(objId); michael@0: michael@0: return objId; michael@0: } michael@0: michael@0: int sCPOWProxyHandler; michael@0: michael@0: class CPOWProxyHandler : public BaseProxyHandler michael@0: { michael@0: public: michael@0: CPOWProxyHandler() michael@0: : BaseProxyHandler(&sCPOWProxyHandler) {} michael@0: virtual ~CPOWProxyHandler() {} michael@0: michael@0: virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE { michael@0: return false; michael@0: } michael@0: michael@0: virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE; michael@0: virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) MOZ_OVERRIDE; michael@0: virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) MOZ_OVERRIDE; michael@0: virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) MOZ_OVERRIDE; michael@0: virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy, michael@0: AutoIdVector &props) MOZ_OVERRIDE; michael@0: virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE; michael@0: virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE; michael@0: michael@0: virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE; michael@0: virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE; michael@0: virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, michael@0: HandleId id, MutableHandleValue vp) MOZ_OVERRIDE; michael@0: virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver, michael@0: JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE; michael@0: virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE; michael@0: michael@0: virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE; michael@0: virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE; michael@0: virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE; michael@0: virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE; michael@0: virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE; michael@0: michael@0: static CPOWProxyHandler singleton; michael@0: }; michael@0: michael@0: CPOWProxyHandler CPOWProxyHandler::singleton; michael@0: michael@0: #define FORWARD(call, args) \ michael@0: JavaScriptParent *parent = ParentOf(proxy); \ michael@0: if (!parent->active()) { \ michael@0: JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \ michael@0: return false; \ michael@0: } \ michael@0: return parent->call args; michael@0: michael@0: bool michael@0: CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) michael@0: { michael@0: FORWARD(preventExtensions, (cx, proxy)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::preventExtensions(JSContext *cx, HandleObject proxy) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: ReturnStatus status; michael@0: if (!CallPreventExtensions(objId, &status)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) michael@0: { michael@0: FORWARD(getPropertyDescriptor, (cx, proxy, id, desc)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: PPropertyDescriptor result; michael@0: if (!CallGetPropertyDescriptor(objId, idstr, &status, &result)) michael@0: return ipcfail(cx); michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: return toDescriptor(cx, result, desc); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, michael@0: HandleId id, MutableHandle desc) michael@0: { michael@0: FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: PPropertyDescriptor result; michael@0: if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result)) michael@0: return ipcfail(cx); michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: return toDescriptor(cx, result, desc); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) michael@0: { michael@0: FORWARD(defineProperty, (cx, proxy, id, desc)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::defineProperty(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: PPropertyDescriptor descriptor; michael@0: if (!fromDescriptor(cx, desc, &descriptor)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: if (!CallDefineProperty(objId, idstr, descriptor, &status)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: FORWARD(getOwnPropertyNames, (cx, proxy, props)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: return getPropertyNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: FORWARD(delete_, (cx, proxy, id, bp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: if (!CallDelete(objId, idstr, &status, bp)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: FORWARD(enumerate, (cx, proxy, props)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: return getPropertyNames(cx, proxy, 0, props); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: FORWARD(has, (cx, proxy, id, bp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: if (!CallHas(objId, idstr, &status, bp)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: FORWARD(hasOwn, (cx, proxy, id, bp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: if (!CallHasOwn(objId, idstr, &status, bp)) michael@0: return ipcfail(cx); michael@0: michael@0: return !!ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver, michael@0: HandleId id, MutableHandleValue vp) michael@0: { michael@0: FORWARD(get, (cx, proxy, receiver, id, vp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::get(JSContext *cx, HandleObject proxy, HandleObject receiver, michael@0: HandleId id, MutableHandleValue vp) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: ObjectId receiverId = idOf(receiver); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: JSVariant val; michael@0: ReturnStatus status; michael@0: if (!CallGet(objId, receiverId, idstr, &status, &val)) michael@0: return ipcfail(cx); michael@0: michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: return toValue(cx, val, vp); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver, michael@0: JS::HandleId id, bool strict, JS::MutableHandleValue vp) michael@0: { michael@0: FORWARD(set, (cx, proxy, receiver, id, strict, vp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver, michael@0: JS::HandleId id, bool strict, JS::MutableHandleValue vp) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: ObjectId receiverId = idOf(receiver); michael@0: michael@0: nsString idstr; michael@0: if (!convertIdToGeckoString(cx, id, &idstr)) michael@0: return false; michael@0: michael@0: JSVariant val; michael@0: if (!toVariant(cx, vp, &val)) michael@0: return false; michael@0: michael@0: ReturnStatus status; michael@0: JSVariant result; michael@0: if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result)) michael@0: return ipcfail(cx); michael@0: michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: return toValue(cx, result, vp); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: FORWARD(keys, (cx, proxy, props)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) michael@0: { michael@0: return getPropertyNames(cx, proxy, JSITER_OWNONLY, props); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) michael@0: { michael@0: FORWARD(isExtensible, (cx, proxy, extensible)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: ReturnStatus status; michael@0: if (!CallIsExtensible(objId, &status, extensible)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: bool michael@0: CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args) michael@0: { michael@0: FORWARD(call, (cx, proxy, args)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: InfallibleTArray vals; michael@0: AutoValueVector outobjects(cx); michael@0: michael@0: RootedValue v(cx); michael@0: for (size_t i = 0; i < args.length() + 2; i++) { michael@0: v = args.base()[i]; michael@0: if (v.isObject()) { michael@0: RootedObject obj(cx, &v.toObject()); michael@0: if (xpc::IsOutObject(cx, obj)) { michael@0: // Make sure it is not an in-out object. michael@0: bool found; michael@0: if (!JS_HasProperty(cx, obj, "value", &found)) michael@0: return false; michael@0: if (found) { michael@0: JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet"); michael@0: return false; michael@0: } michael@0: michael@0: vals.AppendElement(JSParam(void_t())); michael@0: if (!outobjects.append(ObjectValue(*obj))) michael@0: return false; michael@0: continue; michael@0: } michael@0: } michael@0: JSVariant val; michael@0: if (!toVariant(cx, v, &val)) michael@0: return false; michael@0: vals.AppendElement(JSParam(val)); michael@0: } michael@0: michael@0: JSVariant result; michael@0: ReturnStatus status; michael@0: InfallibleTArray outparams; michael@0: if (!CallCall(objId, vals, &status, &result, &outparams)) michael@0: return ipcfail(cx); michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: if (outparams.Length() != outobjects.length()) michael@0: return ipcfail(cx); michael@0: michael@0: RootedObject obj(cx); michael@0: for (size_t i = 0; i < outparams.Length(); i++) { michael@0: // Don't bother doing anything for outparams that weren't set. michael@0: if (outparams[i].type() == JSParam::Tvoid_t) michael@0: continue; michael@0: michael@0: // Take the value the child process returned, and set it on the XPC michael@0: // object. michael@0: if (!toValue(cx, outparams[i], &v)) michael@0: return false; michael@0: michael@0: obj = &outobjects[i].toObject(); michael@0: if (!JS_SetProperty(cx, obj, "value", v)) michael@0: return false; michael@0: } michael@0: michael@0: if (!toValue(cx, result, args.rval())) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: michael@0: bool michael@0: CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx) michael@0: { michael@0: FORWARD(objectClassIs, (cx, proxy, classValue)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: // This function is assumed infallible, so we just return false if the IPC michael@0: // channel fails. michael@0: bool result; michael@0: if (!CallObjectClassIs(objId, classValue, &result)) michael@0: return false; michael@0: michael@0: return result; michael@0: } michael@0: michael@0: const char * michael@0: CPOWProxyHandler::className(JSContext *cx, HandleObject proxy) michael@0: { michael@0: JavaScriptParent *parent = ParentOf(proxy); michael@0: if (!parent->active()) michael@0: return ""; michael@0: return parent->className(cx, proxy); michael@0: } michael@0: michael@0: const char * michael@0: JavaScriptParent::className(JSContext *cx, HandleObject proxy) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: nsString name; michael@0: if (!CallClassName(objId, &name)) michael@0: return ""; michael@0: michael@0: return ToNewCString(name); michael@0: } michael@0: michael@0: void michael@0: CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy) michael@0: { michael@0: ParentOf(proxy)->drop(proxy); michael@0: } michael@0: michael@0: void michael@0: JavaScriptParent::drop(JSObject *obj) michael@0: { michael@0: ObjectId objId = idOf(obj); michael@0: michael@0: objects_.remove(objId); michael@0: if (!inactive_ && !SendDropObject(objId)) michael@0: (void)0; michael@0: decref(); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::init() michael@0: { michael@0: if (!JavaScriptShared::init()) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::makeId(JSContext *cx, JSObject *obj, ObjectId *idp) michael@0: { michael@0: obj = js::CheckedUnwrap(obj, false); michael@0: if (!obj || !IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) { michael@0: JS_ReportError(cx, "cannot ipc non-cpow object"); michael@0: return false; michael@0: } michael@0: michael@0: *idp = idOf(obj); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props) michael@0: { michael@0: ObjectId objId = idOf(proxy); michael@0: michael@0: ReturnStatus status; michael@0: InfallibleTArray names; michael@0: if (!CallGetPropertyNames(objId, flags, &status, &names)) michael@0: return ipcfail(cx); michael@0: if (!ok(cx, status)) michael@0: return false; michael@0: michael@0: for (size_t i = 0; i < names.Length(); i++) { michael@0: RootedId name(cx); michael@0: if (!convertGeckoStringToId(cx, names[i], &name)) michael@0: return false; michael@0: if (!props.append(name)) michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: JSObject * michael@0: JavaScriptParent::unwrap(JSContext *cx, ObjectId objId) michael@0: { michael@0: RootedObject obj(cx, findObject(objId)); michael@0: if (obj) { michael@0: if (!JS_WrapObject(cx, &obj)) michael@0: return nullptr; michael@0: return obj; michael@0: } michael@0: michael@0: if (objId > MAX_CPOW_IDS) { michael@0: JS_ReportError(cx, "unusable CPOW id"); michael@0: return nullptr; michael@0: } michael@0: michael@0: bool callable = !!(objId & OBJECT_IS_CALLABLE); michael@0: michael@0: RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); michael@0: michael@0: RootedValue v(cx, UndefinedValue()); michael@0: ProxyOptions options; michael@0: options.selectDefaultClass(callable); michael@0: obj = NewProxyObject(cx, michael@0: &CPOWProxyHandler::singleton, michael@0: v, michael@0: nullptr, michael@0: global, michael@0: options); michael@0: if (!obj) michael@0: return nullptr; michael@0: michael@0: if (!objects_.add(objId, obj)) michael@0: return nullptr; michael@0: michael@0: // Incref once we know the decref will be called. michael@0: incref(); michael@0: michael@0: SetProxyExtra(obj, 0, PrivateValue(this)); michael@0: SetProxyExtra(obj, 1, DoubleValue(BitwiseCast(objId))); michael@0: return obj; michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::ipcfail(JSContext *cx) michael@0: { michael@0: JS_ReportError(cx, "child process crashed or timedout"); michael@0: return false; michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::ok(JSContext *cx, const ReturnStatus &status) michael@0: { michael@0: if (status.type() == ReturnStatus::TReturnSuccess) michael@0: return true; michael@0: michael@0: if (status.type() == ReturnStatus::TReturnStopIteration) michael@0: return JS_ThrowStopIteration(cx); michael@0: michael@0: RootedValue exn(cx); michael@0: if (!toValue(cx, status.get_ReturnException().exn(), &exn)) michael@0: return false; michael@0: michael@0: JS_SetPendingException(cx, exn); michael@0: return false; michael@0: } michael@0: michael@0: void michael@0: JavaScriptParent::decref() michael@0: { michael@0: refcount_--; michael@0: if (!refcount_) michael@0: delete this; michael@0: } michael@0: michael@0: void michael@0: JavaScriptParent::incref() michael@0: { michael@0: refcount_++; michael@0: } michael@0: michael@0: void michael@0: JavaScriptParent::ActorDestroy(ActorDestroyReason why) michael@0: { michael@0: inactive_ = true; michael@0: } michael@0: michael@0: /* static */ bool michael@0: JavaScriptParent::IsCPOW(JSObject *obj) michael@0: { michael@0: return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton; michael@0: } michael@0: michael@0: /* static */ nsresult michael@0: JavaScriptParent::InstanceOf(JSObject *proxy, const nsID *id, bool *bp) michael@0: { michael@0: JavaScriptParent *parent = ParentOf(proxy); michael@0: if (!parent->active()) michael@0: return NS_ERROR_UNEXPECTED; michael@0: return parent->instanceOf(proxy, id, bp); michael@0: } michael@0: michael@0: nsresult michael@0: JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp) michael@0: { michael@0: ObjectId objId = idOf(obj); michael@0: michael@0: JSIID iid; michael@0: ConvertID(*id, &iid); michael@0: michael@0: ReturnStatus status; michael@0: if (!CallInstanceOf(objId, iid, &status, bp)) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: if (status.type() != ReturnStatus::TReturnSuccess) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* static */ bool michael@0: JavaScriptParent::DOMInstanceOf(JSContext *cx, JSObject *proxy, int prototypeID, int depth, bool *bp) michael@0: { michael@0: FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp)); michael@0: } michael@0: michael@0: bool michael@0: JavaScriptParent::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp) michael@0: { michael@0: ObjectId objId = idOf(obj); michael@0: michael@0: ReturnStatus status; michael@0: if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp)) michael@0: return ipcfail(cx); michael@0: michael@0: return ok(cx, status); michael@0: } michael@0: michael@0: mozilla::ipc::IProtocol* michael@0: JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) michael@0: { michael@0: ContentParent *contentParent = aCtx->GetContentParent(); michael@0: nsAutoPtr actor(contentParent->AllocPJavaScriptParent()); michael@0: if (!actor || !contentParent->RecvPJavaScriptConstructor(actor)) { michael@0: return nullptr; michael@0: } michael@0: return actor.forget(); michael@0: }