LCOV - code coverage report
Current view: top level - js/ipc - JavaScriptShared.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 130 424 30.7 %
Date: 2017-07-14 16:53:18 Functions: 24 50 48.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 "JavaScriptShared.h"
       9             : #include "mozilla/dom/BindingUtils.h"
      10             : #include "mozilla/dom/CPOWManagerGetter.h"
      11             : #include "mozilla/dom/TabChild.h"
      12             : #include "jsfriendapi.h"
      13             : #include "xpcprivate.h"
      14             : #include "WrapperFactory.h"
      15             : #include "mozilla/Preferences.h"
      16             : 
      17             : using namespace js;
      18             : using namespace JS;
      19             : using namespace mozilla;
      20             : using namespace mozilla::jsipc;
      21             : 
      22           6 : IdToObjectMap::IdToObjectMap()
      23           6 :   : table_(SystemAllocPolicy())
      24             : {
      25           6 : }
      26             : 
      27             : bool
      28          10 : IdToObjectMap::init()
      29             : {
      30          10 :     if (table_.initialized())
      31           4 :         return true;
      32           6 :     return table_.init(32);
      33             : }
      34             : 
      35             : void
      36           1 : IdToObjectMap::trace(JSTracer* trc, uint64_t minimumId)
      37             : {
      38           1 :     for (Table::Range r(table_.all()); !r.empty(); r.popFront()) {
      39           0 :         if (r.front().key().serialNumber() >= minimumId)
      40           0 :             JS::TraceEdge(trc, &r.front().value(), "ipc-object");
      41             :     }
      42           1 : }
      43             : 
      44             : void
      45           0 : IdToObjectMap::sweep()
      46             : {
      47           0 :     for (Table::Enum e(table_); !e.empty(); e.popFront()) {
      48           0 :         JS::Heap<JSObject*>* objp = &e.front().value();
      49           0 :         JS_UpdateWeakPointerAfterGC(objp);
      50           0 :         if (!*objp)
      51           0 :             e.removeFront();
      52             :     }
      53           0 : }
      54             : 
      55             : JSObject*
      56           0 : IdToObjectMap::find(ObjectId id)
      57             : {
      58           0 :     Table::Ptr p = table_.lookup(id);
      59           0 :     if (!p)
      60           0 :         return nullptr;
      61           0 :     return p->value();
      62             : }
      63             : 
      64             : JSObject*
      65          29 : IdToObjectMap::findPreserveColor(ObjectId id)
      66             : {
      67          29 :     Table::Ptr p = table_.lookup(id);
      68          29 :     if (!p)
      69           5 :         return nullptr;
      70          24 :     return p->value().unbarrieredGet();
      71             : }
      72             : 
      73             : bool
      74          10 : IdToObjectMap::add(ObjectId id, JSObject* obj)
      75             : {
      76          10 :     return table_.put(id, obj);
      77             : }
      78             : 
      79             : void
      80           0 : IdToObjectMap::remove(ObjectId id)
      81             : {
      82           0 :     table_.remove(id);
      83           0 : }
      84             : 
      85             : void
      86           0 : IdToObjectMap::clear()
      87             : {
      88           0 :     table_.clear();
      89           0 : }
      90             : 
      91             : bool
      92           0 : IdToObjectMap::empty() const
      93             : {
      94           0 :     return table_.empty();
      95             : }
      96             : 
      97             : #ifdef DEBUG
      98             : bool
      99           0 : IdToObjectMap::has(const ObjectId& id, const JSObject* obj) const
     100             : {
     101           0 :     auto p = table_.lookup(id);
     102           0 :     if (!p)
     103           0 :         return false;
     104           0 :     return p->value() == obj;
     105             : }
     106             : #endif
     107             : 
     108             : bool
     109          10 : ObjectToIdMap::init()
     110             : {
     111          10 :     return table_.initialized() || table_.init(32);
     112             : }
     113             : 
     114             : void
     115           2 : ObjectToIdMap::trace(JSTracer* trc)
     116             : {
     117           2 :     table_.trace(trc);
     118           2 : }
     119             : 
     120             : void
     121           0 : ObjectToIdMap::sweep()
     122             : {
     123           0 :     table_.sweep();
     124           0 : }
     125             : 
     126             : ObjectId
     127          29 : ObjectToIdMap::find(JSObject* obj)
     128             : {
     129          29 :     Table::Ptr p = table_.lookup(obj);
     130          29 :     if (!p)
     131           5 :         return ObjectId::nullId();
     132          24 :     return p->value();
     133             : }
     134             : 
     135             : bool
     136           5 : ObjectToIdMap::add(JSContext* cx, JSObject* obj, ObjectId id)
     137             : {
     138           5 :     return table_.put(obj, id);
     139             : }
     140             : 
     141             : void
     142           0 : ObjectToIdMap::remove(JSObject* obj)
     143             : {
     144           0 :     table_.remove(obj);
     145           0 : }
     146             : 
     147             : void
     148           0 : ObjectToIdMap::clear()
     149             : {
     150           0 :     table_.clear();
     151           0 : }
     152             : 
     153             : bool JavaScriptShared::sLoggingInitialized;
     154             : bool JavaScriptShared::sLoggingEnabled;
     155             : bool JavaScriptShared::sStackLoggingEnabled;
     156             : 
     157           3 : JavaScriptShared::JavaScriptShared()
     158             :   : refcount_(1),
     159             :     nextSerialNumber_(1),
     160           3 :     nextCPOWNumber_(1)
     161             : {
     162           3 :     if (!sLoggingInitialized) {
     163           3 :         sLoggingInitialized = true;
     164             : 
     165           3 :         if (PR_GetEnv("MOZ_CPOW_LOG")) {
     166           0 :             sLoggingEnabled = true;
     167           0 :             sStackLoggingEnabled = strstr(PR_GetEnv("MOZ_CPOW_LOG"), "stacks");
     168             :         } else {
     169             :             Preferences::AddBoolVarCache(&sLoggingEnabled,
     170           3 :                                          "dom.ipc.cpows.log.enabled", false);
     171             :             Preferences::AddBoolVarCache(&sStackLoggingEnabled,
     172           3 :                                          "dom.ipc.cpows.log.stack", false);
     173             :         }
     174             :     }
     175           3 : }
     176             : 
     177           0 : JavaScriptShared::~JavaScriptShared()
     178             : {
     179           0 :     MOZ_RELEASE_ASSERT(cpows_.empty());
     180           0 : }
     181             : 
     182             : bool
     183           5 : JavaScriptShared::init()
     184             : {
     185           5 :     if (!objects_.init())
     186           0 :         return false;
     187           5 :     if (!cpows_.init())
     188           0 :         return false;
     189           5 :     if (!unwaivedObjectIds_.init())
     190           0 :         return false;
     191           5 :     if (!waivedObjectIds_.init())
     192           0 :         return false;
     193             : 
     194           5 :     return true;
     195             : }
     196             : 
     197             : void
     198           0 : JavaScriptShared::decref()
     199             : {
     200           0 :     refcount_--;
     201           0 :     if (!refcount_)
     202           0 :         delete this;
     203           0 : }
     204             : 
     205             : void
     206           5 : JavaScriptShared::incref()
     207             : {
     208           5 :     refcount_++;
     209           5 : }
     210             : 
     211             : bool
     212          44 : JavaScriptShared::convertIdToGeckoString(JSContext* cx, JS::HandleId id, nsString* to)
     213             : {
     214          88 :     RootedValue idval(cx);
     215          44 :     if (!JS_IdToValue(cx, id, &idval))
     216           0 :         return false;
     217             : 
     218          88 :     RootedString str(cx, ToString(cx, idval));
     219          44 :     if (!str)
     220           0 :         return false;
     221             : 
     222          44 :     return AssignJSString(cx, *to, str);
     223             : }
     224             : 
     225             : bool
     226           0 : JavaScriptShared::convertGeckoStringToId(JSContext* cx, const nsString& from, JS::MutableHandleId to)
     227             : {
     228           0 :     RootedString str(cx, JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length()));
     229           0 :     if (!str)
     230           0 :         return false;
     231             : 
     232           0 :     return JS_StringToId(cx, str, to);
     233             : }
     234             : 
     235             : bool
     236          44 : JavaScriptShared::toVariant(JSContext* cx, JS::HandleValue from, JSVariant* to)
     237             : {
     238          44 :     switch (JS_TypeOfValue(cx, from)) {
     239             :       case JSTYPE_UNDEFINED:
     240           0 :         *to = UndefinedVariant();
     241           0 :         return true;
     242             : 
     243             :       case JSTYPE_OBJECT:
     244             :       case JSTYPE_FUNCTION:
     245             :       {
     246          88 :         RootedObject obj(cx, from.toObjectOrNull());
     247          44 :         if (!obj) {
     248          15 :             MOZ_ASSERT(from.isNull());
     249          15 :             *to = NullVariant();
     250          15 :             return true;
     251             :         }
     252             : 
     253          29 :         if (xpc_JSObjectIsID(cx, obj)) {
     254           0 :             JSIID iid;
     255           0 :             const nsID* id = xpc_JSObjectToID(cx, obj);
     256           0 :             ConvertID(*id, &iid);
     257           0 :             *to = iid;
     258           0 :             return true;
     259             :         }
     260             : 
     261          58 :         ObjectVariant objVar;
     262          29 :         if (!toObjectVariant(cx, obj, &objVar))
     263           0 :             return false;
     264          29 :         *to = objVar;
     265          29 :         return true;
     266             :       }
     267             : 
     268             :       case JSTYPE_SYMBOL:
     269             :       {
     270           0 :         RootedSymbol sym(cx, from.toSymbol());
     271             : 
     272           0 :         SymbolVariant symVar;
     273           0 :         if (!toSymbolVariant(cx, sym, &symVar))
     274           0 :             return false;
     275           0 :         *to = symVar;
     276           0 :         return true;
     277             :       }
     278             : 
     279             :       case JSTYPE_STRING:
     280             :       {
     281           0 :         nsAutoJSString autoStr;
     282           0 :         if (!autoStr.init(cx, from))
     283           0 :             return false;
     284           0 :         *to = autoStr;
     285           0 :         return true;
     286             :       }
     287             : 
     288             :       case JSTYPE_NUMBER:
     289           0 :         if (from.isInt32())
     290           0 :             *to = double(from.toInt32());
     291             :         else
     292           0 :             *to = from.toDouble();
     293           0 :         return true;
     294             : 
     295             :       case JSTYPE_BOOLEAN:
     296           0 :         *to = from.toBoolean();
     297           0 :         return true;
     298             : 
     299             :       default:
     300           0 :         MOZ_ASSERT(false);
     301             :         return false;
     302             :     }
     303             : }
     304             : 
     305             : bool
     306          44 : JavaScriptShared::fromVariant(JSContext* cx, const JSVariant& from, MutableHandleValue to)
     307             : {
     308          44 :     switch (from.type()) {
     309             :         case JSVariant::TUndefinedVariant:
     310           0 :           to.set(UndefinedValue());
     311           0 :           return true;
     312             : 
     313             :         case JSVariant::TNullVariant:
     314          15 :           to.set(NullValue());
     315          15 :           return true;
     316             : 
     317             :         case JSVariant::TObjectVariant:
     318             :         {
     319          29 :           JSObject* obj = fromObjectVariant(cx, from.get_ObjectVariant());
     320          29 :           if (!obj)
     321           0 :               return false;
     322          29 :           to.set(ObjectValue(*obj));
     323          29 :           return true;
     324             :         }
     325             : 
     326             :         case JSVariant::TSymbolVariant:
     327             :         {
     328           0 :           Symbol* sym = fromSymbolVariant(cx, from.get_SymbolVariant());
     329           0 :           if (!sym)
     330           0 :               return false;
     331           0 :           to.setSymbol(sym);
     332           0 :           return true;
     333             :         }
     334             : 
     335             :         case JSVariant::Tdouble:
     336           0 :           to.set(JS_NumberValue(from.get_double()));
     337           0 :           return true;
     338             : 
     339             :         case JSVariant::Tbool:
     340           0 :           to.setBoolean(from.get_bool());
     341           0 :           return true;
     342             : 
     343             :         case JSVariant::TnsString:
     344             :         {
     345           0 :           const nsString& old = from.get_nsString();
     346           0 :           JSString* str = JS_NewUCStringCopyN(cx, old.BeginReading(), old.Length());
     347           0 :           if (!str)
     348           0 :               return false;
     349           0 :           to.set(StringValue(str));
     350           0 :           return true;
     351             :         }
     352             : 
     353             :         case JSVariant::TJSIID:
     354             :         {
     355             :           nsID iid;
     356           0 :           const JSIID& id = from.get_JSIID();
     357           0 :           ConvertID(id, &iid);
     358             : 
     359           0 :           JSCompartment* compartment = GetContextCompartment(cx);
     360           0 :           RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, compartment));
     361           0 :           JSObject* obj = xpc_NewIDObject(cx, global, iid);
     362           0 :           if (!obj)
     363           0 :               return false;
     364           0 :           to.set(ObjectValue(*obj));
     365           0 :           return true;
     366             :         }
     367             : 
     368             :         default:
     369           0 :           MOZ_CRASH("NYI");
     370             :           return false;
     371             :     }
     372             : }
     373             : 
     374             : bool
     375           0 : JavaScriptShared::toJSIDVariant(JSContext* cx, HandleId from, JSIDVariant* to)
     376             : {
     377           0 :     if (JSID_IS_STRING(from)) {
     378           0 :         nsAutoJSString autoStr;
     379           0 :         if (!autoStr.init(cx, JSID_TO_STRING(from)))
     380           0 :             return false;
     381           0 :         *to = autoStr;
     382           0 :         return true;
     383             :     }
     384           0 :     if (JSID_IS_INT(from)) {
     385           0 :         *to = JSID_TO_INT(from);
     386           0 :         return true;
     387             :     }
     388           0 :     if (JSID_IS_SYMBOL(from)) {
     389           0 :         SymbolVariant symVar;
     390           0 :         if (!toSymbolVariant(cx, JSID_TO_SYMBOL(from), &symVar))
     391           0 :             return false;
     392           0 :         *to = symVar;
     393           0 :         return true;
     394             :     }
     395           0 :     MOZ_ASSERT(false);
     396             :     return false;
     397             : }
     398             : 
     399             : bool
     400           0 : JavaScriptShared::fromJSIDVariant(JSContext* cx, const JSIDVariant& from, MutableHandleId to)
     401             : {
     402           0 :     switch (from.type()) {
     403             :       case JSIDVariant::TSymbolVariant: {
     404           0 :         Symbol* sym = fromSymbolVariant(cx, from.get_SymbolVariant());
     405           0 :         if (!sym)
     406           0 :             return false;
     407           0 :         to.set(SYMBOL_TO_JSID(sym));
     408           0 :         return true;
     409             :       }
     410             : 
     411             :       case JSIDVariant::TnsString:
     412           0 :         return convertGeckoStringToId(cx, from.get_nsString(), to);
     413             : 
     414             :       case JSIDVariant::Tint32_t:
     415           0 :         to.set(INT_TO_JSID(from.get_int32_t()));
     416           0 :         return true;
     417             : 
     418             :       default:
     419           0 :         return false;
     420             :     }
     421             : }
     422             : 
     423             : bool
     424           0 : JavaScriptShared::toSymbolVariant(JSContext* cx, JS::Symbol* symArg, SymbolVariant* symVarp)
     425             : {
     426           0 :     RootedSymbol sym(cx, symArg);
     427           0 :     MOZ_ASSERT(sym);
     428             : 
     429           0 :     SymbolCode code = GetSymbolCode(sym);
     430           0 :     if (static_cast<uint32_t>(code) < WellKnownSymbolLimit) {
     431           0 :         *symVarp = WellKnownSymbol(static_cast<uint32_t>(code));
     432           0 :         return true;
     433             :     }
     434           0 :     if (code == SymbolCode::InSymbolRegistry) {
     435           0 :         nsAutoJSString autoStr;
     436           0 :         if (!autoStr.init(cx, GetSymbolDescription(sym)))
     437           0 :             return false;
     438           0 :         *symVarp = RegisteredSymbol(autoStr);
     439           0 :         return true;
     440             :     }
     441             : 
     442           0 :     JS_ReportErrorASCII(cx, "unique symbol can't be used with CPOW");
     443           0 :     return false;
     444             : }
     445             : 
     446             : JS::Symbol*
     447           0 : JavaScriptShared::fromSymbolVariant(JSContext* cx, const SymbolVariant& symVar)
     448             : {
     449           0 :     switch (symVar.type()) {
     450             :       case SymbolVariant::TWellKnownSymbol: {
     451           0 :         uint32_t which = symVar.get_WellKnownSymbol().which();
     452           0 :         if (which < WellKnownSymbolLimit)
     453           0 :             return GetWellKnownSymbol(cx, static_cast<SymbolCode>(which));
     454           0 :         MOZ_ASSERT(false, "bad child data");
     455             :         return nullptr;
     456             :       }
     457             : 
     458             :       case SymbolVariant::TRegisteredSymbol: {
     459           0 :         nsString key = symVar.get_RegisteredSymbol().key();
     460           0 :         RootedString str(cx, JS_NewUCStringCopyN(cx, key.get(), key.Length()));
     461           0 :         if (!str)
     462           0 :             return nullptr;
     463           0 :         return GetSymbolFor(cx, str);
     464             :       }
     465             : 
     466             :       default:
     467           0 :         return nullptr;
     468             :     }
     469             : }
     470             : 
     471             : /* static */ void
     472           0 : JavaScriptShared::ConvertID(const nsID& from, JSIID* to)
     473             : {
     474           0 :     to->m0() = from.m0;
     475           0 :     to->m1() = from.m1;
     476           0 :     to->m2() = from.m2;
     477           0 :     to->m3_0() = from.m3[0];
     478           0 :     to->m3_1() = from.m3[1];
     479           0 :     to->m3_2() = from.m3[2];
     480           0 :     to->m3_3() = from.m3[3];
     481           0 :     to->m3_4() = from.m3[4];
     482           0 :     to->m3_5() = from.m3[5];
     483           0 :     to->m3_6() = from.m3[6];
     484           0 :     to->m3_7() = from.m3[7];
     485           0 : }
     486             : 
     487             : /* static */ void
     488           0 : JavaScriptShared::ConvertID(const JSIID& from, nsID* to)
     489             : {
     490           0 :     to->m0 = from.m0();
     491           0 :     to->m1 = from.m1();
     492           0 :     to->m2 = from.m2();
     493           0 :     to->m3[0] = from.m3_0();
     494           0 :     to->m3[1] = from.m3_1();
     495           0 :     to->m3[2] = from.m3_2();
     496           0 :     to->m3[3] = from.m3_3();
     497           0 :     to->m3[4] = from.m3_4();
     498           0 :     to->m3[5] = from.m3_5();
     499           0 :     to->m3[6] = from.m3_6();
     500           0 :     to->m3[7] = from.m3_7();
     501           0 : }
     502             : 
     503             : JSObject*
     504          29 : JavaScriptShared::findCPOWById(const ObjectId& objId)
     505             : {
     506          29 :     JSObject* obj = findCPOWByIdPreserveColor(objId);
     507          29 :     if (obj)
     508          24 :         JS::ExposeObjectToActiveJS(obj);
     509          29 :     return obj;
     510             : }
     511             : 
     512             : JSObject*
     513          29 : JavaScriptShared::findCPOWByIdPreserveColor(const ObjectId& objId)
     514             : {
     515          29 :     JSObject* obj = cpows_.findPreserveColor(objId);
     516          29 :     if (!obj)
     517           5 :         return nullptr;
     518             : 
     519          24 :     if (js::gc::EdgeNeedsSweepUnbarriered(&obj)) {
     520           0 :         cpows_.remove(objId);
     521           0 :         return nullptr;
     522             :     }
     523             : 
     524          24 :     return obj;
     525             : }
     526             : 
     527             : JSObject*
     528           0 : JavaScriptShared::findObjectById(JSContext* cx, const ObjectId& objId)
     529             : {
     530           0 :     RootedObject obj(cx, objects_.find(objId));
     531           0 :     if (!obj) {
     532           0 :         JS_ReportErrorASCII(cx, "operation not possible on dead CPOW");
     533           0 :         return nullptr;
     534             :     }
     535             : 
     536             :     // Each process has a dedicated compartment for CPOW targets. All CPOWs
     537             :     // from the other process point to objects in this scope. From there, they
     538             :     // can access objects in other compartments using cross-compartment
     539             :     // wrappers.
     540           0 :     JSAutoCompartment ac(cx, scopeForTargetObjects());
     541           0 :     if (objId.hasXrayWaiver()) {
     542             :         {
     543           0 :             JSAutoCompartment ac2(cx, obj);
     544           0 :             obj = js::ToWindowProxyIfWindow(obj);
     545           0 :             MOZ_ASSERT(obj);
     546             :         }
     547           0 :         if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &obj))
     548           0 :             return nullptr;
     549             :     } else {
     550           0 :         if (!JS_WrapObject(cx, &obj))
     551           0 :             return nullptr;
     552             :     }
     553           0 :     return obj;
     554             : }
     555             : 
     556             : static const uint64_t UnknownPropertyOp = 1;
     557             : 
     558             : bool
     559           0 : JavaScriptShared::fromDescriptor(JSContext* cx, Handle<PropertyDescriptor> desc,
     560             :                                  PPropertyDescriptor* out)
     561             : {
     562           0 :     out->attrs() = desc.attributes();
     563           0 :     if (!toVariant(cx, desc.value(), &out->value()))
     564           0 :         return false;
     565             : 
     566           0 :     if (!toObjectOrNullVariant(cx, desc.object(), &out->obj()))
     567           0 :         return false;
     568             : 
     569           0 :     if (!desc.getter()) {
     570           0 :         out->getter() = 0;
     571           0 :     } else if (desc.hasGetterObject()) {
     572           0 :         JSObject* getter = desc.getterObject();
     573           0 :         ObjectVariant objVar;
     574           0 :         if (!toObjectVariant(cx, getter, &objVar))
     575           0 :             return false;
     576           0 :         out->getter() = objVar;
     577             :     } else {
     578           0 :         MOZ_ASSERT(desc.getter() != JS_PropertyStub);
     579           0 :         out->getter() = UnknownPropertyOp;
     580             :     }
     581             : 
     582           0 :     if (!desc.setter()) {
     583           0 :         out->setter() = 0;
     584           0 :     } else if (desc.hasSetterObject()) {
     585           0 :         JSObject* setter = desc.setterObject();
     586           0 :         ObjectVariant objVar;
     587           0 :         if (!toObjectVariant(cx, setter, &objVar))
     588           0 :             return false;
     589           0 :         out->setter() = objVar;
     590             :     } else {
     591           0 :         MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
     592           0 :         out->setter() = UnknownPropertyOp;
     593             :     }
     594             : 
     595           0 :     return true;
     596             : }
     597             : 
     598             : bool
     599           0 : UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
     600             : {
     601           0 :     JS_ReportErrorASCII(cx, "getter could not be wrapped via CPOWs");
     602           0 :     return false;
     603             : }
     604             : 
     605             : bool
     606           0 : UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
     607             :                           ObjectOpResult& result)
     608             : {
     609           0 :     JS_ReportErrorASCII(cx, "setter could not be wrapped via CPOWs");
     610           0 :     return false;
     611             : }
     612             : 
     613             : bool
     614           0 : JavaScriptShared::toDescriptor(JSContext* cx, const PPropertyDescriptor& in,
     615             :                                MutableHandle<PropertyDescriptor> out)
     616             : {
     617           0 :     out.setAttributes(in.attrs());
     618           0 :     if (!fromVariant(cx, in.value(), out.value()))
     619           0 :         return false;
     620           0 :     out.object().set(fromObjectOrNullVariant(cx, in.obj()));
     621             : 
     622           0 :     if (in.getter().type() == GetterSetter::Tuint64_t && !in.getter().get_uint64_t()) {
     623           0 :         out.setGetter(nullptr);
     624           0 :     } else if (in.attrs() & JSPROP_GETTER) {
     625           0 :         Rooted<JSObject*> getter(cx);
     626           0 :         getter = fromObjectVariant(cx, in.getter().get_ObjectVariant());
     627           0 :         if (!getter)
     628           0 :             return false;
     629           0 :         out.setGetter(JS_DATA_TO_FUNC_PTR(JSGetterOp, getter.get()));
     630             :     } else {
     631           0 :         out.setGetter(UnknownPropertyStub);
     632             :     }
     633             : 
     634           0 :     if (in.setter().type() == GetterSetter::Tuint64_t && !in.setter().get_uint64_t()) {
     635           0 :         out.setSetter(nullptr);
     636           0 :     } else if (in.attrs() & JSPROP_SETTER) {
     637           0 :         Rooted<JSObject*> setter(cx);
     638           0 :         setter = fromObjectVariant(cx, in.setter().get_ObjectVariant());
     639           0 :         if (!setter)
     640           0 :             return false;
     641           0 :         out.setSetter(JS_DATA_TO_FUNC_PTR(JSSetterOp, setter.get()));
     642             :     } else {
     643           0 :         out.setSetter(UnknownStrictPropertyStub);
     644             :     }
     645             : 
     646           0 :     return true;
     647             : }
     648             : 
     649             : bool
     650           0 : JavaScriptShared::toObjectOrNullVariant(JSContext* cx, JSObject* obj, ObjectOrNullVariant* objVarp)
     651             : {
     652           0 :     if (!obj) {
     653           0 :         *objVarp = NullVariant();
     654           0 :         return true;
     655             :     }
     656             : 
     657           0 :     ObjectVariant objVar;
     658           0 :     if (!toObjectVariant(cx, obj, &objVar))
     659           0 :         return false;
     660             : 
     661           0 :     *objVarp = objVar;
     662           0 :     return true;
     663             : }
     664             : 
     665             : JSObject*
     666           0 : JavaScriptShared::fromObjectOrNullVariant(JSContext* cx, const ObjectOrNullVariant& objVar)
     667             : {
     668           0 :     if (objVar.type() == ObjectOrNullVariant::TNullVariant)
     669           0 :         return nullptr;
     670             : 
     671           0 :     return fromObjectVariant(cx, objVar.get_ObjectVariant());
     672             : }
     673             : 
     674          42 : CrossProcessCpowHolder::CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
     675          42 :                                                const InfallibleTArray<CpowEntry>& cpows)
     676             :   : js_(nullptr),
     677             :     cpows_(cpows),
     678          42 :     unwrapped_(false)
     679             : {
     680             :     // Only instantiate the CPOW manager if we might need it later.
     681          42 :     if (cpows.Length())
     682          11 :         js_ = managerGetter->GetCPOWManager();
     683          42 : }
     684             : 
     685          82 : CrossProcessCpowHolder::~CrossProcessCpowHolder()
     686             : {
     687          41 :     if (cpows_.Length() && !unwrapped_) {
     688             :         // This should only happen if a message manager message
     689             :         // containing CPOWs gets ignored for some reason. We need to
     690             :         // unwrap every incoming CPOW in this process to ensure that
     691             :         // the corresponding part of the CPOW in the other process
     692             :         // will eventually be collected. The scope for this object
     693             :         // doesn't really matter, because it immediately becomes
     694             :         // garbage.
     695           0 :         AutoJSAPI jsapi;
     696           0 :         if (!jsapi.Init(xpc::PrivilegedJunkScope()))
     697           0 :             return;
     698           0 :         JSContext* cx = jsapi.cx();
     699           0 :         JS::Rooted<JSObject*> cpows(cx);
     700           0 :         js_->Unwrap(cx, cpows_, &cpows);
     701             :     }
     702          41 : }
     703             : 
     704             : bool
     705          41 : CrossProcessCpowHolder::ToObject(JSContext* cx, JS::MutableHandleObject objp)
     706             : {
     707          41 :     unwrapped_ = true;
     708             : 
     709          41 :     if (!cpows_.Length())
     710          30 :         return true;
     711             : 
     712          11 :     return js_->Unwrap(cx, cpows_, objp);
     713             : }
     714             : 
     715             : bool
     716          11 : JavaScriptShared::Unwrap(JSContext* cx, const InfallibleTArray<CpowEntry>& aCpows,
     717             :                          JS::MutableHandleObject objp)
     718             : {
     719          11 :     objp.set(nullptr);
     720             : 
     721          11 :     if (!aCpows.Length())
     722           0 :         return true;
     723             : 
     724          22 :     RootedObject obj(cx, JS_NewPlainObject(cx));
     725          11 :     if (!obj)
     726           0 :         return false;
     727             : 
     728          22 :     RootedValue v(cx);
     729          22 :     RootedString str(cx);
     730          55 :     for (size_t i = 0; i < aCpows.Length(); i++) {
     731          44 :         const nsString& name = aCpows[i].name();
     732             : 
     733          44 :         if (!fromVariant(cx, aCpows[i].value(), &v))
     734           0 :             return false;
     735             : 
     736          88 :         if (!JS_DefineUCProperty(cx,
     737             :                                  obj,
     738             :                                  name.BeginReading(),
     739          44 :                                  name.Length(),
     740             :                                  v,
     741             :                                  JSPROP_ENUMERATE))
     742             :         {
     743           0 :             return false;
     744             :         }
     745             :     }
     746             : 
     747          11 :     objp.set(obj);
     748          11 :     return true;
     749             : }
     750             : 
     751             : bool
     752          11 : JavaScriptShared::Wrap(JSContext* cx, HandleObject aObj, InfallibleTArray<CpowEntry>* outCpows)
     753             : {
     754          11 :     if (!aObj)
     755           0 :         return true;
     756             : 
     757          22 :     Rooted<IdVector> ids(cx, IdVector(cx));
     758          11 :     if (!JS_Enumerate(cx, aObj, &ids))
     759           0 :         return false;
     760             : 
     761          22 :     RootedId id(cx);
     762          22 :     RootedValue v(cx);
     763          55 :     for (size_t i = 0; i < ids.length(); i++) {
     764          44 :         id = ids[i];
     765             : 
     766          88 :         nsString str;
     767          44 :         if (!convertIdToGeckoString(cx, id, &str))
     768           0 :             return false;
     769             : 
     770          44 :         if (!JS_GetPropertyById(cx, aObj, id, &v))
     771           0 :             return false;
     772             : 
     773          88 :         JSVariant var;
     774          44 :         if (!toVariant(cx, v, &var))
     775           0 :             return false;
     776             : 
     777          44 :         outCpows->AppendElement(CpowEntry(str, var));
     778             :     }
     779             : 
     780          11 :     return true;
     781             : }
     782             : 
     783             : CPOWManager*
     784          20 : mozilla::jsipc::CPOWManagerFor(PJavaScriptParent* aParent)
     785             : {
     786          20 :     return static_cast<JavaScriptParent*>(aParent);
     787             : }
     788             : 
     789             : CPOWManager*
     790          11 : mozilla::jsipc::CPOWManagerFor(PJavaScriptChild* aChild)
     791             : {
     792          11 :     return static_cast<JavaScriptChild*>(aChild);
     793             : }

Generated by: LCOV version 1.13