LCOV - code coverage report
Current view: top level - js/ipc - WrapperAnswer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 452 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       7             : 
       8             : #include "WrapperAnswer.h"
       9             : #include "JavaScriptLogging.h"
      10             : #include "mozilla/dom/ContentChild.h"
      11             : #include "mozilla/dom/BindingUtils.h"
      12             : #include "mozilla/dom/ScriptSettings.h"
      13             : #include "xpcprivate.h"
      14             : #include "js/Class.h"
      15             : #include "jsfriendapi.h"
      16             : 
      17             : using namespace JS;
      18             : using namespace mozilla;
      19             : using namespace mozilla::jsipc;
      20             : 
      21             : // Note - Using AutoJSAPI (rather than AutoEntryScript) for a trap means
      22             : // that we don't expect it to run script. For most of these traps that will only
      23             : // happen if the target is a scripted proxy, which is probably something that we
      24             : // don't want to support over CPOWs. When enough code is fixed up, the long-term
      25             : // plan is to have the JS engine throw if it encounters script when it isn't
      26             : // expecting it.
      27             : using mozilla::dom::AutoJSAPI;
      28             : using mozilla::dom::AutoEntryScript;
      29             : 
      30             : static void
      31           0 : MaybeForceDebugGC()
      32             : {
      33             :     static bool sEnvVarInitialized = false;
      34             :     static bool sDebugGCs = false;
      35             : 
      36           0 :     if (!sEnvVarInitialized)
      37           0 :         sDebugGCs = !!PR_GetEnv("MOZ_DEBUG_DEAD_CPOWS");
      38             : 
      39           0 :     if (sDebugGCs) {
      40           0 :         JSContext* cx = XPCJSContext::Get()->Context();
      41           0 :         PrepareForFullGC(cx);
      42           0 :         GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
      43             :     }
      44           0 : }
      45             : 
      46             : bool
      47           0 : WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs)
      48             : {
      49             :     // By default, we set |undefined| unless we can get a more meaningful
      50             :     // exception.
      51           0 :     *rs = ReturnStatus(ReturnException(JSVariant(UndefinedVariant())));
      52             : 
      53             :     // Note we always return true from this function, since this propagates
      54             :     // to the IPC code, and we don't want a JS failure to cause the death
      55             :     // of the child process.
      56             : 
      57           0 :     JSContext* cx = jsapi.cx();
      58           0 :     RootedValue exn(cx);
      59           0 :     if (!jsapi.HasException())
      60           0 :         return true;
      61             : 
      62           0 :     if (!jsapi.StealException(&exn))
      63           0 :         return true;
      64             : 
      65           0 :     if (JS_IsStopIteration(exn)) {
      66           0 :         *rs = ReturnStatus(ReturnStopIteration());
      67           0 :         return true;
      68             :     }
      69             : 
      70             :     // If this fails, we still don't want to exit. Just return an invalid
      71             :     // exception.
      72           0 :     (void) toVariant(cx, exn, &rs->get_ReturnException().exn());
      73           0 :     return true;
      74             : }
      75             : 
      76             : bool
      77           0 : WrapperAnswer::ok(ReturnStatus* rs)
      78             : {
      79           0 :     *rs = ReturnStatus(ReturnSuccess());
      80           0 :     return true;
      81             : }
      82             : 
      83             : bool
      84           0 : WrapperAnswer::ok(ReturnStatus* rs, const JS::ObjectOpResult& result)
      85             : {
      86             :     *rs = result
      87           0 :           ? ReturnStatus(ReturnSuccess())
      88           0 :           : ReturnStatus(ReturnObjectOpResult(result.failureCode()));
      89           0 :     return true;
      90             : }
      91             : 
      92             : bool
      93           0 : WrapperAnswer::deadCPOW(AutoJSAPI& jsapi, ReturnStatus* rs)
      94             : {
      95           0 :     JSContext* cx = jsapi.cx();
      96           0 :     JS_ClearPendingException(cx);
      97           0 :     *rs = ReturnStatus(ReturnDeadCPOW());
      98           0 :     return true;
      99             : }
     100             : 
     101             : bool
     102           0 : WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs)
     103             : {
     104           0 :     MaybeForceDebugGC();
     105             : 
     106           0 :     AutoJSAPI jsapi;
     107           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     108           0 :         return false;
     109           0 :     JSContext* cx = jsapi.cx();
     110             : 
     111           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     112           0 :     if (!obj)
     113           0 :         return deadCPOW(jsapi, rs);
     114             : 
     115           0 :     ObjectOpResult success;
     116           0 :     if (!JS_PreventExtensions(cx, obj, success))
     117           0 :         return fail(jsapi, rs);
     118             : 
     119           0 :     LOG("%s.preventExtensions()", ReceiverObj(objId));
     120           0 :     return ok(rs, success);
     121             : }
     122             : 
     123             : static void
     124           0 : EmptyDesc(PPropertyDescriptor* desc)
     125             : {
     126           0 :     desc->obj() = LocalObject(0);
     127           0 :     desc->attrs() = 0;
     128           0 :     desc->value() = UndefinedVariant();
     129           0 :     desc->getter() = 0;
     130           0 :     desc->setter() = 0;
     131           0 : }
     132             : 
     133             : bool
     134           0 : WrapperAnswer::RecvGetPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar,
     135             :                                          ReturnStatus* rs, PPropertyDescriptor* out)
     136             : {
     137           0 :     MaybeForceDebugGC();
     138             : 
     139           0 :     AutoJSAPI jsapi;
     140           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     141           0 :         return false;
     142           0 :     JSContext* cx = jsapi.cx();
     143           0 :     EmptyDesc(out);
     144             : 
     145           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     146           0 :     if (!obj)
     147           0 :         return deadCPOW(jsapi, rs);
     148             : 
     149           0 :     LOG("%s.getPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
     150             : 
     151           0 :     RootedId id(cx);
     152           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     153           0 :         return fail(jsapi, rs);
     154             : 
     155           0 :     Rooted<PropertyDescriptor> desc(cx);
     156           0 :     if (!JS_GetPropertyDescriptorById(cx, obj, id, &desc))
     157           0 :         return fail(jsapi, rs);
     158             : 
     159           0 :     if (!fromDescriptor(cx, desc, out))
     160           0 :         return fail(jsapi, rs);
     161             : 
     162           0 :     return ok(rs);
     163             : }
     164             : 
     165             : bool
     166           0 : WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar,
     167             :                                             ReturnStatus* rs, PPropertyDescriptor* out)
     168             : {
     169           0 :     MaybeForceDebugGC();
     170             : 
     171           0 :     AutoJSAPI jsapi;
     172           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     173           0 :         return false;
     174           0 :     JSContext* cx = jsapi.cx();
     175           0 :     EmptyDesc(out);
     176             : 
     177           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     178           0 :     if (!obj)
     179           0 :         return deadCPOW(jsapi, rs);
     180             : 
     181           0 :     LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
     182             : 
     183           0 :     RootedId id(cx);
     184           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     185           0 :         return fail(jsapi, rs);
     186             : 
     187           0 :     Rooted<PropertyDescriptor> desc(cx);
     188           0 :     if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc))
     189           0 :         return fail(jsapi, rs);
     190             : 
     191           0 :     if (!fromDescriptor(cx, desc, out))
     192           0 :         return fail(jsapi, rs);
     193             : 
     194           0 :     return ok(rs);
     195             : }
     196             : 
     197             : bool
     198           0 : WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVar,
     199             :                                   const PPropertyDescriptor& descriptor, ReturnStatus* rs)
     200             : {
     201           0 :     MaybeForceDebugGC();
     202             : 
     203           0 :     AutoJSAPI jsapi;
     204           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     205           0 :         return false;
     206           0 :     JSContext* cx = jsapi.cx();
     207             : 
     208           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     209           0 :     if (!obj)
     210           0 :         return deadCPOW(jsapi, rs);
     211             : 
     212           0 :     LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));
     213             : 
     214           0 :     RootedId id(cx);
     215           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     216           0 :         return fail(jsapi, rs);
     217             : 
     218           0 :     Rooted<PropertyDescriptor> desc(cx);
     219           0 :     if (!toDescriptor(cx, descriptor, &desc))
     220           0 :         return fail(jsapi, rs);
     221             : 
     222           0 :     ObjectOpResult success;
     223           0 :     if (!JS_DefinePropertyById(cx, obj, id, desc, success))
     224           0 :         return fail(jsapi, rs);
     225           0 :     return ok(rs, success);
     226             : }
     227             : 
     228             : bool
     229           0 : WrapperAnswer::RecvDelete(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs)
     230             : {
     231           0 :     MaybeForceDebugGC();
     232             : 
     233           0 :     AutoJSAPI jsapi;
     234           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     235           0 :         return false;
     236           0 :     JSContext* cx = jsapi.cx();
     237             : 
     238           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     239           0 :     if (!obj)
     240           0 :         return deadCPOW(jsapi, rs);
     241             : 
     242           0 :     LOG("delete %s[%s]", ReceiverObj(objId), Identifier(idVar));
     243             : 
     244           0 :     RootedId id(cx);
     245           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     246           0 :         return fail(jsapi, rs);
     247             : 
     248           0 :     ObjectOpResult success;
     249           0 :     if (!JS_DeletePropertyById(cx, obj, id, success))
     250           0 :         return fail(jsapi, rs);
     251           0 :     return ok(rs, success);
     252             : }
     253             : 
     254             : bool
     255           0 : WrapperAnswer::RecvHas(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs,
     256             :                        bool* foundp)
     257             : {
     258           0 :     MaybeForceDebugGC();
     259             : 
     260           0 :     AutoJSAPI jsapi;
     261           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     262           0 :         return false;
     263           0 :     JSContext* cx = jsapi.cx();
     264           0 :     *foundp = false;
     265             : 
     266           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     267           0 :     if (!obj)
     268           0 :         return deadCPOW(jsapi, rs);
     269             : 
     270           0 :     LOG("%s.has(%s)", ReceiverObj(objId), Identifier(idVar));
     271             : 
     272           0 :     RootedId id(cx);
     273           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     274           0 :         return fail(jsapi, rs);
     275             : 
     276           0 :     if (!JS_HasPropertyById(cx, obj, id, foundp))
     277           0 :         return fail(jsapi, rs);
     278           0 :     return ok(rs);
     279             : }
     280             : 
     281             : bool
     282           0 : WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs,
     283             :                           bool* foundp)
     284             : {
     285           0 :     MaybeForceDebugGC();
     286             : 
     287           0 :     AutoJSAPI jsapi;
     288           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     289           0 :         return false;
     290           0 :     JSContext* cx = jsapi.cx();
     291           0 :     *foundp = false;
     292             : 
     293           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     294           0 :     if (!obj)
     295           0 :         return deadCPOW(jsapi, rs);
     296             : 
     297           0 :     LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));
     298             : 
     299           0 :     RootedId id(cx);
     300           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     301           0 :         return fail(jsapi, rs);
     302             : 
     303           0 :     if (!JS_HasOwnPropertyById(cx, obj, id, foundp))
     304           0 :         return fail(jsapi, rs);
     305           0 :     return ok(rs);
     306             : }
     307             : 
     308             : bool
     309           0 : WrapperAnswer::RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
     310             :                        const JSIDVariant& idVar, ReturnStatus* rs, JSVariant* result)
     311             : {
     312           0 :     MaybeForceDebugGC();
     313             : 
     314             :     // We may run scripted getters.
     315           0 :     AutoEntryScript aes(scopeForTargetObjects(),
     316           0 :                         "Cross-Process Object Wrapper 'get'");
     317           0 :     JSContext* cx = aes.cx();
     318             : 
     319             :     // The outparam will be written to the buffer, so it must be set even if
     320             :     // the parent won't read it.
     321           0 :     *result = UndefinedVariant();
     322             : 
     323           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     324           0 :     if (!obj)
     325           0 :         return deadCPOW(aes, rs);
     326             : 
     327           0 :     RootedValue receiver(cx);
     328           0 :     if (!fromVariant(cx, receiverVar, &receiver))
     329           0 :         return fail(aes, rs);
     330             : 
     331           0 :     RootedId id(cx);
     332           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     333           0 :         return fail(aes, rs);
     334             : 
     335           0 :     JS::RootedValue val(cx);
     336           0 :     if (!JS_ForwardGetPropertyTo(cx, obj, id, receiver, &val))
     337           0 :         return fail(aes, rs);
     338             : 
     339           0 :     if (!toVariant(cx, val, result))
     340           0 :         return fail(aes, rs);
     341             : 
     342           0 :     LOG("get %s.%s = %s", ReceiverObj(objId), Identifier(idVar), OutVariant(*result));
     343             : 
     344           0 :     return ok(rs);
     345             : }
     346             : 
     347             : bool
     348           0 : WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar, const JSVariant& value,
     349             :                        const JSVariant& receiverVar, ReturnStatus* rs)
     350             : {
     351           0 :     MaybeForceDebugGC();
     352             : 
     353             :     // We may run scripted setters.
     354           0 :     AutoEntryScript aes(scopeForTargetObjects(),
     355           0 :                         "Cross-Process Object Wrapper 'set'");
     356           0 :     JSContext* cx = aes.cx();
     357             : 
     358           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     359           0 :     if (!obj)
     360           0 :         return deadCPOW(aes, rs);
     361             : 
     362           0 :     LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
     363             : 
     364           0 :     RootedId id(cx);
     365           0 :     if (!fromJSIDVariant(cx, idVar, &id))
     366           0 :         return fail(aes, rs);
     367             : 
     368           0 :     RootedValue val(cx);
     369           0 :     if (!fromVariant(cx, value, &val))
     370           0 :         return fail(aes, rs);
     371             : 
     372           0 :     RootedValue receiver(cx);
     373           0 :     if (!fromVariant(cx, receiverVar, &receiver))
     374           0 :         return fail(aes, rs);
     375             : 
     376           0 :     ObjectOpResult result;
     377           0 :     if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiver, result))
     378           0 :         return fail(aes, rs);
     379             : 
     380           0 :     return ok(rs, result);
     381             : }
     382             : 
     383             : bool
     384           0 : WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result)
     385             : {
     386           0 :     MaybeForceDebugGC();
     387             : 
     388           0 :     AutoJSAPI jsapi;
     389           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     390           0 :         return false;
     391           0 :     JSContext* cx = jsapi.cx();
     392           0 :     *result = false;
     393             : 
     394           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     395           0 :     if (!obj)
     396           0 :         return deadCPOW(jsapi, rs);
     397             : 
     398           0 :     LOG("%s.isExtensible()", ReceiverObj(objId));
     399             : 
     400             :     bool extensible;
     401           0 :     if (!JS_IsExtensible(cx, obj, &extensible))
     402           0 :         return fail(jsapi, rs);
     403             : 
     404           0 :     *result = !!extensible;
     405           0 :     return ok(rs);
     406             : }
     407             : 
     408             : bool
     409           0 : WrapperAnswer::RecvCallOrConstruct(const ObjectId& objId,
     410             :                                    InfallibleTArray<JSParam>&& argv,
     411             :                                    const bool& construct,
     412             :                                    ReturnStatus* rs,
     413             :                                    JSVariant* result,
     414             :                                    nsTArray<JSParam>* outparams)
     415             : {
     416           0 :     MaybeForceDebugGC();
     417             : 
     418           0 :     AutoEntryScript aes(scopeForTargetObjects(),
     419           0 :                         "Cross-Process Object Wrapper call/construct");
     420           0 :     JSContext* cx = aes.cx();
     421             : 
     422             :     // The outparam will be written to the buffer, so it must be set even if
     423             :     // the parent won't read it.
     424           0 :     *result = UndefinedVariant();
     425             : 
     426           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     427           0 :     if (!obj)
     428           0 :         return deadCPOW(aes, rs);
     429             : 
     430           0 :     MOZ_ASSERT(argv.Length() >= 2);
     431             : 
     432           0 :     RootedValue objv(cx);
     433           0 :     if (!fromVariant(cx, argv[0], &objv))
     434           0 :         return fail(aes, rs);
     435             : 
     436           0 :     *result = JSVariant(UndefinedVariant());
     437             : 
     438           0 :     AutoValueVector vals(cx);
     439           0 :     AutoValueVector outobjects(cx);
     440           0 :     for (size_t i = 0; i < argv.Length(); i++) {
     441           0 :         if (argv[i].type() == JSParam::Tvoid_t) {
     442             :             // This is an outparam.
     443           0 :             RootedObject obj(cx, xpc::NewOutObject(cx));
     444           0 :             if (!obj)
     445           0 :                 return fail(aes, rs);
     446           0 :             if (!outobjects.append(ObjectValue(*obj)))
     447           0 :                 return fail(aes, rs);
     448           0 :             if (!vals.append(ObjectValue(*obj)))
     449           0 :                 return fail(aes, rs);
     450             :         } else {
     451           0 :             RootedValue v(cx);
     452           0 :             if (!fromVariant(cx, argv[i].get_JSVariant(), &v))
     453           0 :                 return fail(aes, rs);
     454           0 :             if (!vals.append(v))
     455           0 :                 return fail(aes, rs);
     456             :         }
     457             :     }
     458             : 
     459           0 :     RootedValue rval(cx);
     460             :     {
     461           0 :         HandleValueArray args = HandleValueArray::subarray(vals, 2, vals.length() - 2);
     462           0 :         if (construct) {
     463           0 :             RootedObject obj(cx);
     464           0 :             if (!JS::Construct(cx, vals[0], args, &obj))
     465           0 :                 return fail(aes, rs);
     466           0 :             rval.setObject(*obj);
     467             :         } else {
     468           0 :             if(!JS::Call(cx, vals[1], vals[0], args, &rval))
     469           0 :                 return fail(aes, rs);
     470             :         }
     471             :     }
     472             : 
     473           0 :     if (!toVariant(cx, rval, result))
     474           0 :         return fail(aes, rs);
     475             : 
     476             :     // Prefill everything with a dummy jsval.
     477           0 :     for (size_t i = 0; i < outobjects.length(); i++)
     478           0 :         outparams->AppendElement(JSParam(void_t()));
     479             : 
     480             :     // Go through each argument that was an outparam, retrieve the "value"
     481             :     // field, and add it to a temporary list. We need to do this separately
     482             :     // because the outparams vector is not rooted.
     483           0 :     vals.clear();
     484           0 :     for (size_t i = 0; i < outobjects.length(); i++) {
     485           0 :         RootedObject obj(cx, &outobjects[i].toObject());
     486             : 
     487           0 :         RootedValue v(cx);
     488             :         bool found;
     489           0 :         if (JS_HasProperty(cx, obj, "value", &found)) {
     490           0 :             if (!JS_GetProperty(cx, obj, "value", &v))
     491           0 :                 return fail(aes, rs);
     492             :         } else {
     493           0 :             v = UndefinedValue();
     494             :         }
     495           0 :         if (!vals.append(v))
     496           0 :             return fail(aes, rs);
     497             :     }
     498             : 
     499             :     // Copy the outparams. If any outparam is already set to a void_t, we
     500             :     // treat this as the outparam never having been set.
     501           0 :     for (size_t i = 0; i < vals.length(); i++) {
     502           0 :         JSVariant variant;
     503           0 :         if (!toVariant(cx, vals[i], &variant))
     504           0 :             return fail(aes, rs);
     505           0 :         outparams->ReplaceElementAt(i, JSParam(variant));
     506             :     }
     507             : 
     508           0 :     LOG("%s.call(%s) = %s", ReceiverObj(objId), argv, OutVariant(*result));
     509             : 
     510           0 :     return ok(rs);
     511             : }
     512             : 
     513             : bool
     514           0 : WrapperAnswer::RecvHasInstance(const ObjectId& objId, const JSVariant& vVar, ReturnStatus* rs, bool* bp)
     515             : {
     516           0 :     MaybeForceDebugGC();
     517             : 
     518           0 :     AutoJSAPI jsapi;
     519           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     520           0 :         return false;
     521           0 :     JSContext* cx = jsapi.cx();
     522             : 
     523           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     524           0 :     if (!obj)
     525           0 :         return deadCPOW(jsapi, rs);
     526             : 
     527           0 :     LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));
     528             : 
     529           0 :     RootedValue val(cx);
     530           0 :     if (!fromVariant(cx, vVar, &val))
     531           0 :         return fail(jsapi, rs);
     532             : 
     533           0 :     if (!JS_HasInstance(cx, obj, val, bp))
     534           0 :         return fail(jsapi, rs);
     535             : 
     536           0 :     return ok(rs);
     537             : }
     538             : 
     539             : bool
     540           0 : WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
     541             :                                    uint32_t* classValue)
     542             : {
     543           0 :     MaybeForceDebugGC();
     544             : 
     545           0 :     *classValue = uint32_t(js::ESClass::Other);
     546             : 
     547           0 :     AutoJSAPI jsapi;
     548           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     549           0 :         return false;
     550           0 :     JSContext* cx = jsapi.cx();
     551             : 
     552           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     553           0 :     if (!obj)
     554           0 :         return deadCPOW(jsapi, rs);
     555             : 
     556           0 :     LOG("%s.getBuiltinClass()", ReceiverObj(objId));
     557             : 
     558             :     js::ESClass cls;
     559           0 :     if (!js::GetBuiltinClass(cx, obj, &cls))
     560           0 :         return fail(jsapi, rs);
     561             : 
     562           0 :     *classValue = uint32_t(cls);
     563           0 :     return ok(rs);
     564             : }
     565             : 
     566             : bool
     567           0 : WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs,
     568             :                            uint32_t* ans)
     569             : {
     570           0 :     MaybeForceDebugGC();
     571             : 
     572           0 :     *ans = uint32_t(IsArrayAnswer::NotArray);
     573             : 
     574           0 :     AutoJSAPI jsapi;
     575           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     576           0 :         return false;
     577           0 :     JSContext* cx = jsapi.cx();
     578             : 
     579           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     580           0 :     if (!obj)
     581           0 :         return deadCPOW(jsapi, rs);
     582             : 
     583           0 :     LOG("%s.isArray()", ReceiverObj(objId));
     584             : 
     585             :     IsArrayAnswer answer;
     586           0 :     if (!JS::IsArray(cx, obj, &answer))
     587           0 :         return fail(jsapi, rs);
     588             : 
     589           0 :     *ans = uint32_t(answer);
     590           0 :     return ok(rs);
     591             : }
     592             : 
     593             : bool
     594           0 : WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name)
     595             : {
     596           0 :     MaybeForceDebugGC();
     597             : 
     598           0 :     AutoJSAPI jsapi;
     599           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     600           0 :         return false;
     601           0 :     JSContext* cx = jsapi.cx();
     602             : 
     603           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     604           0 :     if (!obj) {
     605             :         // This is very unfortunate, but we have no choice.
     606           0 :         *name = "<dead CPOW>";
     607           0 :         return true;
     608             :     }
     609             : 
     610           0 :     LOG("%s.className()", ReceiverObj(objId));
     611             : 
     612           0 :     *name = js::ObjectClassName(cx, obj);
     613           0 :     return true;
     614             : }
     615             : 
     616             : bool
     617           0 : WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result)
     618             : {
     619           0 :     MaybeForceDebugGC();
     620             : 
     621           0 :     *result = NullVariant();
     622             : 
     623           0 :     AutoJSAPI jsapi;
     624           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     625           0 :         return false;
     626           0 :     JSContext* cx = jsapi.cx();
     627             : 
     628           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     629           0 :     if (!obj)
     630           0 :         return deadCPOW(jsapi, rs);
     631             : 
     632           0 :     JS::RootedObject proto(cx);
     633           0 :     if (!JS_GetPrototype(cx, obj, &proto))
     634           0 :         return fail(jsapi, rs);
     635             : 
     636           0 :     if (!toObjectOrNullVariant(cx, proto, result))
     637           0 :         return fail(jsapi, rs);
     638             : 
     639           0 :     LOG("getPrototype(%s)", ReceiverObj(objId));
     640             : 
     641           0 :     return ok(rs);
     642             : }
     643             : 
     644             : bool
     645           0 : WrapperAnswer::RecvGetPrototypeIfOrdinary(const ObjectId& objId, ReturnStatus* rs, bool* isOrdinary,
     646             :                                           ObjectOrNullVariant* result)
     647             : {
     648           0 :     MaybeForceDebugGC();
     649             : 
     650           0 :     *result = NullVariant();
     651           0 :     *isOrdinary = false;
     652             : 
     653           0 :     AutoJSAPI jsapi;
     654           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     655           0 :         return false;
     656           0 :     JSContext* cx = jsapi.cx();
     657             : 
     658           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     659           0 :     if (!obj)
     660           0 :         return deadCPOW(jsapi, rs);
     661             : 
     662           0 :     JS::RootedObject proto(cx);
     663           0 :     if (!JS_GetPrototypeIfOrdinary(cx, obj, isOrdinary, &proto))
     664           0 :         return fail(jsapi, rs);
     665             : 
     666           0 :     if (!toObjectOrNullVariant(cx, proto, result))
     667           0 :         return fail(jsapi, rs);
     668             : 
     669           0 :     LOG("getPrototypeIfOrdinary(%s)", ReceiverObj(objId));
     670             : 
     671           0 :     return ok(rs);
     672             : }
     673             : 
     674             : bool
     675           0 : WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
     676             :                                   nsString* source, uint32_t* flags)
     677             : {
     678           0 :     MaybeForceDebugGC();
     679             : 
     680           0 :     AutoJSAPI jsapi;
     681           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     682           0 :         return false;
     683           0 :     JSContext* cx = jsapi.cx();
     684             : 
     685           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     686           0 :     if (!obj)
     687           0 :         return deadCPOW(jsapi, rs);
     688             : 
     689           0 :     RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
     690           0 :     if (!sourceJSStr)
     691           0 :         return fail(jsapi, rs);
     692           0 :     nsAutoJSString sourceStr;
     693           0 :     if (!sourceStr.init(cx, sourceJSStr))
     694           0 :         return fail(jsapi, rs);
     695           0 :     source->Assign(sourceStr);
     696             : 
     697           0 :     *flags = JS_GetRegExpFlags(cx, obj);
     698             : 
     699           0 :     return ok(rs);
     700             : }
     701             : 
     702             : bool
     703           0 : WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
     704             :                                    ReturnStatus* rs, nsTArray<JSIDVariant>* ids)
     705             : {
     706           0 :     MaybeForceDebugGC();
     707             : 
     708           0 :     AutoJSAPI jsapi;
     709           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     710           0 :         return false;
     711           0 :     JSContext* cx = jsapi.cx();
     712             : 
     713           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     714           0 :     if (!obj)
     715           0 :         return deadCPOW(jsapi, rs);
     716             : 
     717           0 :     LOG("%s.getPropertyKeys()", ReceiverObj(objId));
     718             : 
     719           0 :     AutoIdVector props(cx);
     720           0 :     if (!js::GetPropertyKeys(cx, obj, flags, &props))
     721           0 :         return fail(jsapi, rs);
     722             : 
     723           0 :     for (size_t i = 0; i < props.length(); i++) {
     724           0 :         JSIDVariant id;
     725           0 :         if (!toJSIDVariant(cx, props[i], &id))
     726           0 :             return fail(jsapi, rs);
     727             : 
     728           0 :         ids->AppendElement(id);
     729             :     }
     730             : 
     731           0 :     return ok(rs);
     732             : }
     733             : 
     734             : bool
     735           0 : WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs,
     736             :                               bool* instanceof)
     737             : {
     738           0 :     MaybeForceDebugGC();
     739             : 
     740           0 :     AutoJSAPI jsapi;
     741           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     742           0 :         return false;
     743           0 :     JSContext* cx = jsapi.cx();
     744             : 
     745           0 :     *instanceof = false;
     746             : 
     747           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     748           0 :     if (!obj)
     749           0 :         return deadCPOW(jsapi, rs);
     750             : 
     751           0 :     LOG("%s.instanceOf()", ReceiverObj(objId));
     752             : 
     753             :     nsID nsiid;
     754           0 :     ConvertID(iid, &nsiid);
     755             : 
     756           0 :     nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
     757           0 :     if (rv != NS_OK)
     758           0 :         return fail(jsapi, rs);
     759             : 
     760           0 :     return ok(rs);
     761             : }
     762             : 
     763             : bool
     764           0 : WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
     765             :                                  const int& depth, ReturnStatus* rs, bool* instanceof)
     766             : {
     767           0 :     MaybeForceDebugGC();
     768             : 
     769           0 :     AutoJSAPI jsapi;
     770           0 :     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
     771           0 :         return false;
     772           0 :     JSContext* cx = jsapi.cx();
     773           0 :     *instanceof = false;
     774             : 
     775           0 :     RootedObject obj(cx, findObjectById(cx, objId));
     776           0 :     if (!obj)
     777           0 :         return deadCPOW(jsapi, rs);
     778             : 
     779           0 :     LOG("%s.domInstanceOf()", ReceiverObj(objId));
     780             : 
     781             :     bool tmp;
     782           0 :     if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
     783           0 :         return fail(jsapi, rs);
     784           0 :     *instanceof = tmp;
     785             : 
     786           0 :     return ok(rs);
     787             : }
     788             : 
     789             : bool
     790           0 : WrapperAnswer::RecvDropObject(const ObjectId& objId)
     791             : {
     792           0 :     JSObject* obj = objects_.findPreserveColor(objId);
     793           0 :     if (obj) {
     794           0 :         objectIdMap(objId.hasXrayWaiver()).remove(obj);
     795           0 :         objects_.remove(objId);
     796             :     }
     797           0 :     return true;
     798             : }

Generated by: LCOV version 1.13