js/ipc/JavaScriptParent.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=4 sw=4 et tw=80:
     3  *
     4  * This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #include "JavaScriptParent.h"
     9 #include "mozilla/dom/ContentParent.h"
    10 #include "nsJSUtils.h"
    11 #include "jsfriendapi.h"
    12 #include "jsproxy.h"
    13 #include "jswrapper.h"
    14 #include "HeapAPI.h"
    15 #include "xpcprivate.h"
    16 #include "mozilla/Casting.h"
    18 using namespace js;
    19 using namespace JS;
    20 using namespace mozilla;
    21 using namespace mozilla::jsipc;
    22 using namespace mozilla::dom;
    24 JavaScriptParent::JavaScriptParent()
    25   : refcount_(1),
    26     inactive_(false)
    27 {
    28 }
    30 static inline JavaScriptParent *
    31 ParentOf(JSObject *obj)
    32 {
    33     MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
    34     return reinterpret_cast<JavaScriptParent *>(GetProxyExtra(obj, 0).toPrivate());
    35 }
    37 ObjectId
    38 JavaScriptParent::idOf(JSObject *obj)
    39 {
    40     MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
    42     Value v = GetProxyExtra(obj, 1);
    43     MOZ_ASSERT(v.isDouble());
    45     ObjectId objId = BitwiseCast<uint64_t>(v.toDouble());
    46     MOZ_ASSERT(findObject(objId) == obj);
    47     MOZ_ASSERT(objId);
    49     return objId;
    50 }
    52 int sCPOWProxyHandler;
    54 class CPOWProxyHandler : public BaseProxyHandler
    55 {
    56   public:
    57     CPOWProxyHandler()
    58       : BaseProxyHandler(&sCPOWProxyHandler) {}
    59     virtual ~CPOWProxyHandler() {}
    61     virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE {
    62         return false;
    63     }
    65     virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
    66     virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
    67                                        MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
    68     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
    69                                           MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
    70     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
    71                                 MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
    72     virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy,
    73                                      AutoIdVector &props) MOZ_OVERRIDE;
    74     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
    75     virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
    77     virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
    78     virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
    79     virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
    80                      HandleId id, MutableHandleValue vp) MOZ_OVERRIDE;
    81     virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
    82                      JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE;
    83     virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
    85     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
    86     virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
    87     virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
    88     virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
    89     virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
    91     static CPOWProxyHandler singleton;
    92 };
    94 CPOWProxyHandler CPOWProxyHandler::singleton;
    96 #define FORWARD(call, args)                                             \
    97     JavaScriptParent *parent = ParentOf(proxy);                         \
    98     if (!parent->active()) {                                            \
    99         JS_ReportError(cx, "cannot use a CPOW whose process is gone");  \
   100         return false;                                                   \
   101     }                                                                   \
   102     return parent->call args;
   104 bool
   105 CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
   106 {
   107     FORWARD(preventExtensions, (cx, proxy));
   108 }
   110 bool
   111 JavaScriptParent::preventExtensions(JSContext *cx, HandleObject proxy)
   112 {
   113     ObjectId objId = idOf(proxy);
   115     ReturnStatus status;
   116     if (!CallPreventExtensions(objId, &status))
   117         return ipcfail(cx);
   119     return ok(cx, status);
   120 }
   122 bool
   123 CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
   124                                         MutableHandle<JSPropertyDescriptor> desc)
   125 {
   126     FORWARD(getPropertyDescriptor, (cx, proxy, id, desc));
   127 }
   129 bool
   130 JavaScriptParent::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
   131                                         MutableHandle<JSPropertyDescriptor> desc)
   132 {
   133     ObjectId objId = idOf(proxy);
   135     nsString idstr;
   136     if (!convertIdToGeckoString(cx, id, &idstr))
   137         return false;
   139     ReturnStatus status;
   140     PPropertyDescriptor result;
   141     if (!CallGetPropertyDescriptor(objId, idstr, &status, &result))
   142         return ipcfail(cx);
   143     if (!ok(cx, status))
   144         return false;
   146     return toDescriptor(cx, result, desc);
   147 }
   149 bool
   150 CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
   151                                            HandleId id, MutableHandle<JSPropertyDescriptor> desc)
   152 {
   153     FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc));
   154 }
   156 bool
   157 JavaScriptParent::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
   158                                            MutableHandle<JSPropertyDescriptor> desc)
   159 {
   160     ObjectId objId = idOf(proxy);
   162     nsString idstr;
   163     if (!convertIdToGeckoString(cx, id, &idstr))
   164         return false;
   166     ReturnStatus status;
   167     PPropertyDescriptor result;
   168     if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result))
   169         return ipcfail(cx);
   170     if (!ok(cx, status))
   171         return false;
   173     return toDescriptor(cx, result, desc);
   174 }
   176 bool
   177 CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
   178                                  MutableHandle<JSPropertyDescriptor> desc)
   179 {
   180     FORWARD(defineProperty, (cx, proxy, id, desc));
   181 }
   183 bool
   184 JavaScriptParent::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
   185                                  MutableHandle<JSPropertyDescriptor> desc)
   186 {
   187     ObjectId objId = idOf(proxy);
   189     nsString idstr;
   190     if (!convertIdToGeckoString(cx, id, &idstr))
   191         return false;
   193     PPropertyDescriptor descriptor;
   194     if (!fromDescriptor(cx, desc, &descriptor))
   195         return false;
   197     ReturnStatus status;
   198     if (!CallDefineProperty(objId, idstr, descriptor, &status))
   199         return ipcfail(cx);
   201     return ok(cx, status);
   202 }
   204 bool
   205 CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   206 {
   207     FORWARD(getOwnPropertyNames, (cx, proxy, props));
   208 }
   210 bool
   211 JavaScriptParent::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   212 {
   213     return getPropertyNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
   214 }
   216 bool
   217 CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   218 {
   219     FORWARD(delete_, (cx, proxy, id, bp));
   220 }
   222 bool
   223 JavaScriptParent::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   224 {
   225     ObjectId objId = idOf(proxy);
   227     nsString idstr;
   228     if (!convertIdToGeckoString(cx, id, &idstr))
   229         return false;
   231     ReturnStatus status;
   232     if (!CallDelete(objId, idstr, &status, bp))
   233         return ipcfail(cx);
   235     return ok(cx, status);
   236 }
   238 bool
   239 CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   240 {
   241     FORWARD(enumerate, (cx, proxy, props));
   242 }
   244 bool
   245 JavaScriptParent::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   246 {
   247     return getPropertyNames(cx, proxy, 0, props);
   248 }
   250 bool
   251 CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   252 {
   253     FORWARD(has, (cx, proxy, id, bp));
   254 }
   256 bool
   257 JavaScriptParent::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   258 {
   259     ObjectId objId = idOf(proxy);
   261     nsString idstr;
   262     if (!convertIdToGeckoString(cx, id, &idstr))
   263         return false;
   265     ReturnStatus status;
   266     if (!CallHas(objId, idstr, &status, bp))
   267         return ipcfail(cx);
   269     return ok(cx, status);
   270 }
   272 bool
   273 CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   274 {
   275     FORWARD(hasOwn, (cx, proxy, id, bp));
   276 }
   278 bool
   279 JavaScriptParent::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
   280 {
   281     ObjectId objId = idOf(proxy);
   283     nsString idstr;
   284     if (!convertIdToGeckoString(cx, id, &idstr))
   285         return false;
   287     ReturnStatus status;
   288     if (!CallHasOwn(objId, idstr, &status, bp))
   289         return ipcfail(cx);
   291     return !!ok(cx, status);
   292 }
   294 bool
   295 CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
   296                       HandleId id, MutableHandleValue vp)
   297 {
   298     FORWARD(get, (cx, proxy, receiver, id, vp));
   299 }
   301 bool
   302 JavaScriptParent::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
   303                       HandleId id, MutableHandleValue vp)
   304 {
   305     ObjectId objId = idOf(proxy);
   306     ObjectId receiverId = idOf(receiver);
   308     nsString idstr;
   309     if (!convertIdToGeckoString(cx, id, &idstr))
   310         return false;
   312     JSVariant val;
   313     ReturnStatus status;
   314     if (!CallGet(objId, receiverId, idstr, &status, &val))
   315         return ipcfail(cx);
   317     if (!ok(cx, status))
   318         return false;
   320     return toValue(cx, val, vp);
   321 }
   323 bool
   324 CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
   325                       JS::HandleId id, bool strict, JS::MutableHandleValue vp)
   326 {
   327     FORWARD(set, (cx, proxy, receiver, id, strict, vp));
   328 }
   330 bool
   331 JavaScriptParent::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
   332                       JS::HandleId id, bool strict, JS::MutableHandleValue vp)
   333 {
   334     ObjectId objId = idOf(proxy);
   335     ObjectId receiverId = idOf(receiver);
   337     nsString idstr;
   338     if (!convertIdToGeckoString(cx, id, &idstr))
   339         return false;
   341     JSVariant val;
   342     if (!toVariant(cx, vp, &val))
   343         return false;
   345     ReturnStatus status;
   346     JSVariant result;
   347     if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result))
   348         return ipcfail(cx);
   350     if (!ok(cx, status))
   351         return false;
   353     return toValue(cx, result, vp);
   354 }
   356 bool
   357 CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   358 {
   359     FORWARD(keys, (cx, proxy, props));
   360 }
   362 bool
   363 JavaScriptParent::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
   364 {
   365     return getPropertyNames(cx, proxy, JSITER_OWNONLY, props);
   366 }
   368 bool
   369 CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
   370 {
   371     FORWARD(isExtensible, (cx, proxy, extensible));
   372 }
   374 bool
   375 JavaScriptParent::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
   376 {
   377     ObjectId objId = idOf(proxy);
   379     ReturnStatus status;
   380     if (!CallIsExtensible(objId, &status, extensible))
   381         return ipcfail(cx);
   383     return ok(cx, status);
   384 }
   386 bool
   387 CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
   388 {
   389     FORWARD(call, (cx, proxy, args));
   390 }
   392 bool
   393 JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
   394 {
   395     ObjectId objId = idOf(proxy);
   397     InfallibleTArray<JSParam> vals;
   398     AutoValueVector outobjects(cx);
   400     RootedValue v(cx);
   401     for (size_t i = 0; i < args.length() + 2; i++) {
   402         v = args.base()[i];
   403         if (v.isObject()) {
   404             RootedObject obj(cx, &v.toObject());
   405             if (xpc::IsOutObject(cx, obj)) {
   406                 // Make sure it is not an in-out object.
   407                 bool found;
   408                 if (!JS_HasProperty(cx, obj, "value", &found))
   409                     return false;
   410                 if (found) {
   411                     JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet");
   412                     return false;
   413                 }
   415                 vals.AppendElement(JSParam(void_t()));
   416                 if (!outobjects.append(ObjectValue(*obj)))
   417                     return false;
   418                 continue;
   419             }
   420         }
   421         JSVariant val;
   422         if (!toVariant(cx, v, &val))
   423             return false;
   424         vals.AppendElement(JSParam(val));
   425     }
   427     JSVariant result;
   428     ReturnStatus status;
   429     InfallibleTArray<JSParam> outparams;
   430     if (!CallCall(objId, vals, &status, &result, &outparams))
   431         return ipcfail(cx);
   432     if (!ok(cx, status))
   433         return false;
   435     if (outparams.Length() != outobjects.length())
   436         return ipcfail(cx);
   438     RootedObject obj(cx);
   439     for (size_t i = 0; i < outparams.Length(); i++) {
   440         // Don't bother doing anything for outparams that weren't set.
   441         if (outparams[i].type() == JSParam::Tvoid_t)
   442             continue;
   444         // Take the value the child process returned, and set it on the XPC
   445         // object.
   446         if (!toValue(cx, outparams[i], &v))
   447             return false;
   449         obj = &outobjects[i].toObject();
   450         if (!JS_SetProperty(cx, obj, "value", v))
   451             return false;
   452     }
   454     if (!toValue(cx, result, args.rval()))
   455         return false;
   457     return true;
   458 }
   461 bool
   462 CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx)
   463 {
   464     FORWARD(objectClassIs, (cx, proxy, classValue));
   465 }
   467 bool
   468 JavaScriptParent::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
   469 {
   470     ObjectId objId = idOf(proxy);
   472     // This function is assumed infallible, so we just return false if the IPC
   473     // channel fails.
   474     bool result;
   475     if (!CallObjectClassIs(objId, classValue, &result))
   476         return false;
   478     return result;
   479 }
   481 const char *
   482 CPOWProxyHandler::className(JSContext *cx, HandleObject proxy)
   483 {
   484     JavaScriptParent *parent = ParentOf(proxy);
   485     if (!parent->active())
   486         return "<dead CPOW>";
   487     return parent->className(cx, proxy);
   488 }
   490 const char *
   491 JavaScriptParent::className(JSContext *cx, HandleObject proxy)
   492 {
   493     ObjectId objId = idOf(proxy);
   495     nsString name;
   496     if (!CallClassName(objId, &name))
   497         return "<error>";
   499     return ToNewCString(name);
   500 }
   502 void
   503 CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
   504 {
   505     ParentOf(proxy)->drop(proxy);
   506 }
   508 void
   509 JavaScriptParent::drop(JSObject *obj)
   510 {
   511     ObjectId objId = idOf(obj);
   513     objects_.remove(objId);
   514     if (!inactive_ && !SendDropObject(objId))
   515         (void)0;
   516     decref();
   517 }
   519 bool
   520 JavaScriptParent::init()
   521 {
   522     if (!JavaScriptShared::init())
   523         return false;
   525     return true;
   526 }
   528 bool
   529 JavaScriptParent::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
   530 {
   531     obj = js::CheckedUnwrap(obj, false);
   532     if (!obj || !IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
   533         JS_ReportError(cx, "cannot ipc non-cpow object");
   534         return false;
   535     }
   537     *idp = idOf(obj);
   538     return true;
   539 }
   541 bool
   542 JavaScriptParent::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props)
   543 {
   544     ObjectId objId = idOf(proxy);
   546     ReturnStatus status;
   547     InfallibleTArray<nsString> names;
   548     if (!CallGetPropertyNames(objId, flags, &status, &names))
   549         return ipcfail(cx);
   550     if (!ok(cx, status))
   551         return false;
   553     for (size_t i = 0; i < names.Length(); i++) {
   554         RootedId name(cx);
   555         if (!convertGeckoStringToId(cx, names[i], &name))
   556             return false;
   557         if (!props.append(name))
   558             return false;
   559     }
   561     return true;
   562 }
   564 JSObject *
   565 JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
   566 {
   567     RootedObject obj(cx, findObject(objId));
   568     if (obj) {
   569         if (!JS_WrapObject(cx, &obj))
   570             return nullptr;
   571         return obj;
   572     }
   574     if (objId > MAX_CPOW_IDS) {
   575         JS_ReportError(cx, "unusable CPOW id");
   576         return nullptr;
   577     }
   579     bool callable = !!(objId & OBJECT_IS_CALLABLE);
   581     RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
   583     RootedValue v(cx, UndefinedValue());
   584     ProxyOptions options;
   585     options.selectDefaultClass(callable);
   586     obj = NewProxyObject(cx,
   587                          &CPOWProxyHandler::singleton,
   588                          v,
   589                          nullptr,
   590                          global,
   591                          options);
   592     if (!obj)
   593         return nullptr;
   595     if (!objects_.add(objId, obj))
   596         return nullptr;
   598     // Incref once we know the decref will be called.
   599     incref();
   601     SetProxyExtra(obj, 0, PrivateValue(this));
   602     SetProxyExtra(obj, 1, DoubleValue(BitwiseCast<double>(objId)));
   603     return obj;
   604 }
   606 bool
   607 JavaScriptParent::ipcfail(JSContext *cx)
   608 {
   609     JS_ReportError(cx, "child process crashed or timedout");
   610     return false;
   611 }
   613 bool
   614 JavaScriptParent::ok(JSContext *cx, const ReturnStatus &status)
   615 {
   616     if (status.type() == ReturnStatus::TReturnSuccess)
   617         return true;
   619     if (status.type() == ReturnStatus::TReturnStopIteration)
   620         return JS_ThrowStopIteration(cx);
   622     RootedValue exn(cx);
   623     if (!toValue(cx, status.get_ReturnException().exn(), &exn))
   624         return false;
   626     JS_SetPendingException(cx, exn);
   627     return false;
   628 }
   630 void
   631 JavaScriptParent::decref()
   632 {
   633     refcount_--;
   634     if (!refcount_)
   635         delete this;
   636 }
   638 void
   639 JavaScriptParent::incref()
   640 {
   641     refcount_++;
   642 }
   644 void
   645 JavaScriptParent::ActorDestroy(ActorDestroyReason why)
   646 {
   647     inactive_ = true;
   648 }
   650 /* static */ bool
   651 JavaScriptParent::IsCPOW(JSObject *obj)
   652 {
   653     return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
   654 }
   656 /* static */ nsresult
   657 JavaScriptParent::InstanceOf(JSObject *proxy, const nsID *id, bool *bp)
   658 {
   659     JavaScriptParent *parent = ParentOf(proxy);
   660     if (!parent->active())
   661         return NS_ERROR_UNEXPECTED;
   662     return parent->instanceOf(proxy, id, bp);
   663 }
   665 nsresult
   666 JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp)
   667 {
   668     ObjectId objId = idOf(obj);
   670     JSIID iid;
   671     ConvertID(*id, &iid);
   673     ReturnStatus status;
   674     if (!CallInstanceOf(objId, iid, &status, bp))
   675         return NS_ERROR_UNEXPECTED;
   677     if (status.type() != ReturnStatus::TReturnSuccess)
   678         return NS_ERROR_UNEXPECTED;
   680     return NS_OK;
   681 }
   683 /* static */ bool
   684 JavaScriptParent::DOMInstanceOf(JSContext *cx, JSObject *proxy, int prototypeID, int depth, bool *bp)
   685 {
   686     FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
   687 }
   689 bool
   690 JavaScriptParent::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp)
   691 {
   692     ObjectId objId = idOf(obj);
   694     ReturnStatus status;
   695     if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
   696         return ipcfail(cx);
   698     return ok(cx, status);
   699 }
   701 mozilla::ipc::IProtocol*
   702 JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx)
   703 {
   704     ContentParent *contentParent = aCtx->GetContentParent();
   705     nsAutoPtr<PJavaScriptParent> actor(contentParent->AllocPJavaScriptParent());
   706     if (!actor || !contentParent->RecvPJavaScriptConstructor(actor)) {
   707         return nullptr;
   708     }
   709     return actor.forget();
   710 }

mercurial