LCOV - code coverage report
Current view: top level - js/ipc - JavaScriptShared.h (source / functions) Hit Total Coverage
Test: output.info Lines: 25 34 73.5 %
Date: 2017-07-14 16:53:18 Functions: 13 20 65.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=8 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             : #ifndef mozilla_jsipc_JavaScriptShared_h__
       9             : #define mozilla_jsipc_JavaScriptShared_h__
      10             : 
      11             : #include "mozilla/dom/DOMTypes.h"
      12             : #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
      13             : #include "mozilla/jsipc/PJavaScript.h"
      14             : #include "js/GCHashTable.h"
      15             : #include "nsJSUtils.h"
      16             : 
      17             : namespace mozilla {
      18             : namespace jsipc {
      19             : 
      20             : class ObjectId {
      21             :   public:
      22             :     // Use 47 bits at most, to be safe, since jsval privates are encoded as
      23             :     // doubles. See bug 1065811 comment 12 for an explanation.
      24             :     static const size_t SERIAL_NUMBER_BITS = 47;
      25             :     static const size_t FLAG_BITS = 1;
      26             :     static const uint64_t SERIAL_NUMBER_MAX = (uint64_t(1) << SERIAL_NUMBER_BITS) - 1;
      27             : 
      28          34 :     explicit ObjectId(uint64_t serialNumber, bool hasXrayWaiver)
      29          34 :       : serialNumber_(serialNumber), hasXrayWaiver_(hasXrayWaiver)
      30             :     {
      31          34 :         if (MOZ_UNLIKELY(serialNumber == 0 || serialNumber > SERIAL_NUMBER_MAX))
      32           0 :             MOZ_CRASH("Bad CPOW Id");
      33          34 :     }
      34             : 
      35          24 :     bool operator==(const ObjectId& other) const {
      36          24 :         bool equal = serialNumber() == other.serialNumber();
      37          24 :         MOZ_ASSERT_IF(equal, hasXrayWaiver() == other.hasXrayWaiver());
      38          24 :         return equal;
      39             :     }
      40             : 
      41          29 :     bool isNull() { return !serialNumber_; }
      42             : 
      43         189 :     uint64_t serialNumber() const { return serialNumber_; }
      44         140 :     bool hasXrayWaiver() const { return hasXrayWaiver_; }
      45          68 :     uint64_t serialize() const {
      46          68 :         MOZ_ASSERT(serialNumber(), "Don't send a null ObjectId over IPC");
      47          68 :         return uint64_t((serialNumber() << FLAG_BITS) | ((hasXrayWaiver() ? 1 : 0) << 0));
      48             :     }
      49             : 
      50           5 :     static ObjectId nullId() { return ObjectId(); }
      51          29 :     static ObjectId deserialize(uint64_t data) {
      52          29 :         return ObjectId(data >> FLAG_BITS, data & 1);
      53             :     }
      54             : 
      55             :     // For use with StructGCPolicy.
      56           0 :     void trace(JSTracer*) const {}
      57           0 :     bool needsSweep() const { return false; }
      58             : 
      59             :   private:
      60           5 :     ObjectId() : serialNumber_(0), hasXrayWaiver_(false) {}
      61             : 
      62             :     uint64_t serialNumber_ : SERIAL_NUMBER_BITS;
      63             :     bool hasXrayWaiver_ : 1;
      64             : };
      65             : 
      66             : class JavaScriptShared;
      67             : 
      68             : // DefaultHasher<T> requires that T coerce to an integral type. We could make
      69             : // ObjectId do that, but doing so would weaken our type invariants, so we just
      70             : // reimplement it manually.
      71             : struct ObjectIdHasher
      72             : {
      73             :     typedef ObjectId Lookup;
      74          39 :     static js::HashNumber hash(const Lookup& l) {
      75          39 :         return l.serialize();
      76             :     }
      77          24 :     static bool match(const ObjectId& k, const ObjectId& l) {
      78          24 :         return k == l;
      79             :     }
      80             :     static void rekey(ObjectId& k, const ObjectId& newKey) {
      81             :         k = newKey;
      82             :     }
      83             : };
      84             : 
      85             : // Map ids -> JSObjects
      86           0 : class IdToObjectMap
      87             : {
      88             :     typedef js::HashMap<ObjectId, JS::Heap<JSObject*>, ObjectIdHasher, js::SystemAllocPolicy> Table;
      89             : 
      90             :   public:
      91             :     IdToObjectMap();
      92             : 
      93             :     bool init();
      94             :     void trace(JSTracer* trc, uint64_t minimumId = 0);
      95             :     void sweep();
      96             : 
      97             :     bool add(ObjectId id, JSObject* obj);
      98             :     JSObject* find(ObjectId id);
      99             :     JSObject* findPreserveColor(ObjectId id);
     100             :     void remove(ObjectId id);
     101             : 
     102             :     void clear();
     103             :     bool empty() const;
     104             : 
     105             : #ifdef DEBUG
     106             :     bool has(const ObjectId& id, const JSObject* obj) const;
     107             : #endif
     108             : 
     109             :   private:
     110             :     Table table_;
     111             : };
     112             : 
     113             : // Map JSObjects -> ids
     114           6 : class ObjectToIdMap
     115             : {
     116             :     using Hasher = js::MovableCellHasher<JS::Heap<JSObject*>>;
     117             :     using Table = JS::GCHashMap<JS::Heap<JSObject*>, ObjectId, Hasher, js::SystemAllocPolicy>;
     118             : 
     119             :   public:
     120             :     bool init();
     121             :     void trace(JSTracer* trc);
     122             :     void sweep();
     123             : 
     124             :     bool add(JSContext* cx, JSObject* obj, ObjectId id);
     125             :     ObjectId find(JSObject* obj);
     126             :     void remove(JSObject* obj);
     127             :     void clear();
     128             : 
     129             :   private:
     130             :     Table table_;
     131             : };
     132             : 
     133             : class Logging;
     134             : 
     135             : class JavaScriptShared : public CPOWManager
     136             : {
     137             :   public:
     138             :     JavaScriptShared();
     139             :     virtual ~JavaScriptShared();
     140             : 
     141             :     bool init();
     142             : 
     143             :     void decref();
     144             :     void incref();
     145             : 
     146             :     bool Unwrap(JSContext* cx, const InfallibleTArray<CpowEntry>& aCpows, JS::MutableHandleObject objp);
     147             :     bool Wrap(JSContext* cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry>* outCpows);
     148             : 
     149             :   protected:
     150             :     bool toVariant(JSContext* cx, JS::HandleValue from, JSVariant* to);
     151             :     bool fromVariant(JSContext* cx, const JSVariant& from, JS::MutableHandleValue to);
     152             : 
     153             :     bool toJSIDVariant(JSContext* cx, JS::HandleId from, JSIDVariant* to);
     154             :     bool fromJSIDVariant(JSContext* cx, const JSIDVariant& from, JS::MutableHandleId to);
     155             : 
     156             :     bool toSymbolVariant(JSContext* cx, JS::Symbol* sym, SymbolVariant* symVarp);
     157             :     JS::Symbol* fromSymbolVariant(JSContext* cx, const SymbolVariant& symVar);
     158             : 
     159             :     bool fromDescriptor(JSContext* cx, JS::Handle<JS::PropertyDescriptor> desc,
     160             :                         PPropertyDescriptor* out);
     161             :     bool toDescriptor(JSContext* cx, const PPropertyDescriptor& in,
     162             :                       JS::MutableHandle<JS::PropertyDescriptor> out);
     163             : 
     164             :     bool toObjectOrNullVariant(JSContext* cx, JSObject* obj, ObjectOrNullVariant* objVarp);
     165             :     JSObject* fromObjectOrNullVariant(JSContext* cx, const ObjectOrNullVariant& objVar);
     166             : 
     167             :     bool convertIdToGeckoString(JSContext* cx, JS::HandleId id, nsString* to);
     168             :     bool convertGeckoStringToId(JSContext* cx, const nsString& from, JS::MutableHandleId id);
     169             : 
     170             :     virtual bool toObjectVariant(JSContext* cx, JSObject* obj, ObjectVariant* objVarp) = 0;
     171             :     virtual JSObject* fromObjectVariant(JSContext* cx, const ObjectVariant& objVar) = 0;
     172             : 
     173             :     static void ConvertID(const nsID& from, JSIID* to);
     174             :     static void ConvertID(const JSIID& from, nsID* to);
     175             : 
     176             :     JSObject* findCPOWById(const ObjectId& objId);
     177             :     JSObject* findCPOWByIdPreserveColor(const ObjectId& objId);
     178             :     JSObject* findObjectById(JSContext* cx, const ObjectId& objId);
     179             : 
     180             : #ifdef DEBUG
     181           0 :     bool hasCPOW(const ObjectId& objId, const JSObject* obj) {
     182           0 :         MOZ_ASSERT(obj);
     183           0 :         return findCPOWByIdPreserveColor(objId) == obj;
     184             :     }
     185             : #endif
     186             : 
     187           0 :     static bool LoggingEnabled() { return sLoggingEnabled; }
     188           0 :     static bool StackLoggingEnabled() { return sStackLoggingEnabled; }
     189             : 
     190             :     friend class Logging;
     191             : 
     192             :     virtual bool isParent() = 0;
     193             : 
     194             :     virtual JSObject* scopeForTargetObjects() = 0;
     195             : 
     196             :   protected:
     197             :     uintptr_t refcount_;
     198             : 
     199             :     IdToObjectMap objects_;
     200             :     IdToObjectMap cpows_;
     201             : 
     202             :     uint64_t nextSerialNumber_;
     203             : 
     204             :     // nextCPOWNumber_ should be the value of nextSerialNumber_ in the other
     205             :     // process. The next new CPOW we get should have this serial number.
     206             :     uint64_t nextCPOWNumber_;
     207             : 
     208             :     // CPOW references can be weak, and any object we store in a map may be
     209             :     // GCed (at which point the CPOW will report itself "dead" to the owner).
     210             :     // This means that we don't want to store any js::Wrappers in the CPOW map,
     211             :     // because CPOW will die if the wrapper is GCed, even if the underlying
     212             :     // object is still alive.
     213             :     //
     214             :     // This presents a tricky situation for Xray waivers, since they're normally
     215             :     // represented as a special same-compartment wrapper. We have to strip them
     216             :     // off before putting them in the id-to-object and object-to-id maps, so we
     217             :     // need a way of distinguishing them at lookup-time.
     218             :     //
     219             :     // For the id-to-object map, we encode waiver-or-not information into the id
     220             :     // itself, which lets us do the right thing when accessing the object.
     221             :     //
     222             :     // For the object-to-id map, we just keep two maps, one for each type.
     223             :     ObjectToIdMap unwaivedObjectIds_;
     224             :     ObjectToIdMap waivedObjectIds_;
     225          34 :     ObjectToIdMap& objectIdMap(bool waiver) {
     226          34 :         return waiver ? waivedObjectIds_ : unwaivedObjectIds_;
     227             :     }
     228             : 
     229             :     static bool sLoggingInitialized;
     230             :     static bool sLoggingEnabled;
     231             :     static bool sStackLoggingEnabled;
     232             : };
     233             : 
     234             : } // namespace jsipc
     235             : } // namespace mozilla
     236             : 
     237             : #endif

Generated by: LCOV version 1.13