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

Generated by: LCOV version 1.13-14-ga5dd952