LCOV - code coverage report
Current view: top level - dom/base - StructuredCloneHolder.h (source / functions) Hit Total Coverage
Test: output.info Lines: 13 28 46.4 %
Date: 2017-07-14 16:53:18 Functions: 5 10 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef mozilla_dom_StructuredCloneHolder_h
       7             : #define mozilla_dom_StructuredCloneHolder_h
       8             : 
       9             : #include "jsapi.h"
      10             : #include "js/StructuredClone.h"
      11             : #include "mozilla/Move.h"
      12             : #include "mozilla/UniquePtr.h"
      13             : #include "mozilla/dom/BindingDeclarations.h"
      14             : #include "nsISupports.h"
      15             : #include "nsTArray.h"
      16             : 
      17             : #ifdef DEBUG
      18             : #include "nsIThread.h"
      19             : #endif
      20             : 
      21             : class nsIInputStream;
      22             : 
      23             : namespace mozilla {
      24             : class ErrorResult;
      25             : namespace layers {
      26             : class Image;
      27             : }
      28             : 
      29             : namespace gfx {
      30             : class DataSourceSurface;
      31             : }
      32             : 
      33             : namespace dom {
      34             : 
      35             : class StructuredCloneHolderBase
      36             : {
      37             : public:
      38             :   typedef JS::StructuredCloneScope StructuredCloneScope;
      39             : 
      40             :   StructuredCloneHolderBase(StructuredCloneScope aScope = StructuredCloneScope::SameProcessSameThread);
      41             :   virtual ~StructuredCloneHolderBase();
      42             : 
      43             :   StructuredCloneHolderBase(StructuredCloneHolderBase&& aOther) = default;
      44             : 
      45             :   // These methods should be implemented in order to clone data.
      46             :   // Read more documentation in js/public/StructuredClone.h.
      47             : 
      48             :   virtual JSObject* CustomReadHandler(JSContext* aCx,
      49             :                                       JSStructuredCloneReader* aReader,
      50             :                                       uint32_t aTag,
      51             :                                       uint32_t aIndex) = 0;
      52             : 
      53             :   virtual bool CustomWriteHandler(JSContext* aCx,
      54             :                                   JSStructuredCloneWriter* aWriter,
      55             :                                   JS::Handle<JSObject*> aObj) = 0;
      56             : 
      57             :   // This method has to be called when this object is not needed anymore.
      58             :   // It will free memory and the buffer. This has to be called because
      59             :   // otherwise the buffer will be freed in the DTOR of this class and at that
      60             :   // point we cannot use the overridden methods.
      61             :   void Clear();
      62             : 
      63             :   // If these 3 methods are not implement, transfering objects will not be
      64             :   // allowed. Otherwise only arrayBuffers will be transferred.
      65             : 
      66             :   virtual bool
      67             :   CustomReadTransferHandler(JSContext* aCx,
      68             :                             JSStructuredCloneReader* aReader,
      69             :                             uint32_t aTag,
      70             :                             void* aContent,
      71             :                             uint64_t aExtraData,
      72             :                             JS::MutableHandleObject aReturnObject);
      73             : 
      74             :   virtual bool
      75             :   CustomWriteTransferHandler(JSContext* aCx,
      76             :                              JS::Handle<JSObject*> aObj,
      77             :                              // Output:
      78             :                              uint32_t* aTag,
      79             :                              JS::TransferableOwnership* aOwnership,
      80             :                              void** aContent,
      81             :                              uint64_t* aExtraData);
      82             : 
      83             :   virtual void
      84             :   CustomFreeTransferHandler(uint32_t aTag,
      85             :                             JS::TransferableOwnership aOwnership,
      86             :                             void* aContent,
      87             :                             uint64_t aExtraData);
      88             : 
      89             :   // These methods are what you should use to read/write data.
      90             : 
      91             :   // Execute the serialization of aValue using the Structured Clone Algorithm.
      92             :   // The data can read back using Read().
      93             :   bool Write(JSContext* aCx,
      94             :              JS::Handle<JS::Value> aValue);
      95             : 
      96             :   // Like Write() but it supports the transferring of objects and handling
      97             :   // of cloning policy.
      98             :   bool Write(JSContext* aCx,
      99             :              JS::Handle<JS::Value> aValue,
     100             :              JS::Handle<JS::Value> aTransfer,
     101             :              JS::CloneDataPolicy cloneDataPolicy);
     102             : 
     103             :   // If Write() has been called, this method retrieves data and stores it into
     104             :   // aValue.
     105             :   bool Read(JSContext* aCx,
     106             :             JS::MutableHandle<JS::Value> aValue);
     107             : 
     108           2 :   bool HasData() const
     109             :   {
     110           2 :     return !!mBuffer;
     111             :   }
     112             : 
     113             :   JSStructuredCloneData& BufferData() const
     114             :   {
     115             :     MOZ_ASSERT(mBuffer, "Write() has never been called.");
     116             :     return mBuffer->data();
     117             :   }
     118             : 
     119             : protected:
     120             :   UniquePtr<JSAutoStructuredCloneBuffer> mBuffer;
     121             : 
     122             :   StructuredCloneScope mStructuredCloneScope;
     123             : 
     124             : #ifdef DEBUG
     125             :   bool mClearCalled;
     126             : #endif
     127             : };
     128             : 
     129             : class BlobImpl;
     130             : class MessagePort;
     131             : class MessagePortIdentifier;
     132             : 
     133             : class StructuredCloneHolder : public StructuredCloneHolderBase
     134             : {
     135             : public:
     136             :   enum CloningSupport
     137             :   {
     138             :     CloningSupported,
     139             :     CloningNotSupported
     140             :   };
     141             : 
     142             :   enum TransferringSupport
     143             :   {
     144             :     TransferringSupported,
     145             :     TransferringNotSupported
     146             :   };
     147             : 
     148             :   // If cloning is supported, this object will clone objects such as Blobs,
     149             :   // FileList, ImageData, etc.
     150             :   // If transferring is supported, we will transfer MessagePorts and in the
     151             :   // future other transferrable objects.
     152             :   // The StructuredCloneScope is useful to know where the cloned/transferred
     153             :   // data can be read and written. Additional checks about the nature of the
     154             :   // objects will be done based on this scope value because not all the
     155             :   // objects can be sent between threads or processes.
     156             :   explicit StructuredCloneHolder(CloningSupport aSupportsCloning,
     157             :                                  TransferringSupport aSupportsTransferring,
     158             :                                  StructuredCloneScope aStructuredCloneScope);
     159             :   virtual ~StructuredCloneHolder();
     160             : 
     161             :   StructuredCloneHolder(StructuredCloneHolder&& aOther) = default;
     162             : 
     163             :   // Normally you should just use Write() and Read().
     164             : 
     165             :   void Write(JSContext* aCx,
     166             :              JS::Handle<JS::Value> aValue,
     167             :              ErrorResult &aRv);
     168             : 
     169             :   void Write(JSContext* aCx,
     170             :              JS::Handle<JS::Value> aValue,
     171             :              JS::Handle<JS::Value> aTransfer,
     172             :              JS::CloneDataPolicy cloneDataPolicy,
     173             :              ErrorResult &aRv);
     174             : 
     175             :   void Read(nsISupports* aParent,
     176             :             JSContext* aCx,
     177             :             JS::MutableHandle<JS::Value> aValue,
     178             :             ErrorResult &aRv);
     179             : 
     180             :   // Call this method to know if this object is keeping some DOM object alive.
     181           0 :   bool HasClonedDOMObjects() const
     182             :   {
     183           0 :     return !mBlobImplArray.IsEmpty() ||
     184           0 :            !mWasmModuleArray.IsEmpty() ||
     185           0 :            !mClonedSurfaces.IsEmpty() ||
     186           0 :            !mInputStreamArray.IsEmpty();
     187             :   }
     188             : 
     189           0 :   nsTArray<RefPtr<BlobImpl>>& BlobImpls()
     190             :   {
     191           0 :     MOZ_ASSERT(mSupportsCloning, "Blobs cannot be taken/set if cloning is not supported.");
     192           0 :     return mBlobImplArray;
     193             :   }
     194             : 
     195           6 :   nsTArray<RefPtr<JS::WasmModule>>& WasmModules()
     196             :   {
     197           6 :     MOZ_ASSERT(mSupportsCloning, "WasmModules cannot be taken/set if cloning is not supported.");
     198           6 :     return mWasmModuleArray;
     199             :   }
     200             : 
     201           0 :   nsTArray<nsCOMPtr<nsIInputStream>>& InputStreams()
     202             :   {
     203           0 :     MOZ_ASSERT(mSupportsCloning, "InputStreams cannot be taken/set if cloning is not supported.");
     204           0 :     return mInputStreamArray;
     205             :   }
     206             : 
     207           0 :   StructuredCloneScope CloneScope() const
     208             :   {
     209           0 :     return mStructuredCloneScope;
     210             :   }
     211             : 
     212             :   // The parent object is set internally just during the Read(). This method
     213             :   // can be used by read functions to retrieve it.
     214           0 :   nsISupports* ParentDuringRead() const
     215             :   {
     216           0 :     return mParent;
     217             :   }
     218             : 
     219             :   // This must be called if the transferring has ports generated by Read().
     220             :   // MessagePorts are not thread-safe and they must be retrieved in the thread
     221             :   // where they are created.
     222          46 :   nsTArray<RefPtr<MessagePort>>&& TakeTransferredPorts()
     223             :   {
     224          46 :     MOZ_ASSERT(mSupportsTransferring);
     225          46 :     return Move(mTransferredPorts);
     226             :   }
     227             : 
     228             :   // This method uses TakeTransferredPorts() to populate a sequence of
     229             :   // MessagePorts for WebIDL binding classes.
     230             :   bool
     231             :   TakeTransferredPortsAsSequence(Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts);
     232             : 
     233          98 :   nsTArray<MessagePortIdentifier>& PortIdentifiers() const
     234             :   {
     235          98 :     MOZ_ASSERT(mSupportsTransferring);
     236          98 :     return mPortIdentifiers;
     237             :   }
     238             : 
     239           6 :   nsTArray<RefPtr<gfx::DataSourceSurface>>& GetSurfaces()
     240             :   {
     241           6 :     return mClonedSurfaces;
     242             :   }
     243             : 
     244             :   // Implementations of the virtual methods to allow cloning of objects which
     245             :   // JS engine itself doesn't clone.
     246             : 
     247             :   virtual JSObject* CustomReadHandler(JSContext* aCx,
     248             :                                       JSStructuredCloneReader* aReader,
     249             :                                       uint32_t aTag,
     250             :                                       uint32_t aIndex) override;
     251             : 
     252             :   virtual bool CustomWriteHandler(JSContext* aCx,
     253             :                                   JSStructuredCloneWriter* aWriter,
     254             :                                   JS::Handle<JSObject*> aObj) override;
     255             : 
     256             :   virtual bool CustomReadTransferHandler(JSContext* aCx,
     257             :                                          JSStructuredCloneReader* aReader,
     258             :                                          uint32_t aTag,
     259             :                                          void* aContent,
     260             :                                          uint64_t aExtraData,
     261             :                                          JS::MutableHandleObject aReturnObject) override;
     262             : 
     263             :   virtual bool CustomWriteTransferHandler(JSContext* aCx,
     264             :                                           JS::Handle<JSObject*> aObj,
     265             :                                           uint32_t* aTag,
     266             :                                           JS::TransferableOwnership* aOwnership,
     267             :                                           void** aContent,
     268             :                                           uint64_t* aExtraData) override;
     269             : 
     270             :   virtual void CustomFreeTransferHandler(uint32_t aTag,
     271             :                                          JS::TransferableOwnership aOwnership,
     272             :                                          void* aContent,
     273             :                                          uint64_t aExtraData) override;
     274             : 
     275             :   // These 2 static methods are useful to read/write fully serializable objects.
     276             :   // They can be used by custom StructuredCloneHolderBase classes to
     277             :   // serialize objects such as ImageData, CryptoKey, RTCCertificate, etc.
     278             : 
     279             :   static JSObject* ReadFullySerializableObjects(JSContext* aCx,
     280             :                                                 JSStructuredCloneReader* aReader,
     281             :                                                 uint32_t aTag);
     282             : 
     283             :   static bool  WriteFullySerializableObjects(JSContext* aCx,
     284             :                                              JSStructuredCloneWriter* aWriter,
     285             :                                              JS::Handle<JSObject*> aObj);
     286             : 
     287             :   static const JSStructuredCloneCallbacks sCallbacks;
     288             : 
     289             : protected:
     290             :   // If you receive a buffer from IPC, you can use this method to retrieve a
     291             :   // JS::Value. It can happen that you want to pre-populate the array of Blobs
     292             :   // and/or the PortIdentifiers.
     293             :   void ReadFromBuffer(nsISupports* aParent,
     294             :                       JSContext* aCx,
     295             :                       JSStructuredCloneData& aBuffer,
     296             :                       JS::MutableHandle<JS::Value> aValue,
     297             :                       ErrorResult &aRv);
     298             : 
     299             :   void ReadFromBuffer(nsISupports* aParent,
     300             :                       JSContext* aCx,
     301             :                       JSStructuredCloneData& aBuffer,
     302             :                       uint32_t aAlgorithmVersion,
     303             :                       JS::MutableHandle<JS::Value> aValue,
     304             :                       ErrorResult &aRv);
     305             : 
     306             :   bool mSupportsCloning;
     307             :   bool mSupportsTransferring;
     308             : 
     309             :   // Used for cloning blobs in the structured cloning algorithm.
     310             :   nsTArray<RefPtr<BlobImpl>> mBlobImplArray;
     311             : 
     312             :   // Used for cloning JS::WasmModules in the structured cloning algorithm.
     313             :   nsTArray<RefPtr<JS::WasmModule>> mWasmModuleArray;
     314             : 
     315             :   // Used for cloning InputStream in the structured cloning algorithm.
     316             :   nsTArray<nsCOMPtr<nsIInputStream>> mInputStreamArray;
     317             : 
     318             :   // This is used for sharing the backend of ImageBitmaps.
     319             :   // The DataSourceSurface object must be thread-safely reference-counted.
     320             :   // The DataSourceSurface object will not be written ever via any ImageBitmap
     321             :   // instance, so no race condition will occur.
     322             :   nsTArray<RefPtr<gfx::DataSourceSurface>> mClonedSurfaces;
     323             : 
     324             :   // This raw pointer is only set within ::Read() and is unset by the end.
     325             :   nsISupports* MOZ_NON_OWNING_REF mParent;
     326             : 
     327             :   // This array contains the ports once we've finished the reading. It's
     328             :   // generated from the mPortIdentifiers array.
     329             :   nsTArray<RefPtr<MessagePort>> mTransferredPorts;
     330             : 
     331             :   // This array contains the identifiers of the MessagePorts. Based on these we
     332             :   // are able to reconnect the new transferred ports with the other
     333             :   // MessageChannel ports.
     334             :   mutable nsTArray<MessagePortIdentifier> mPortIdentifiers;
     335             : 
     336             : #ifdef DEBUG
     337             :   nsCOMPtr<nsIEventTarget> mCreationEventTarget;
     338             : #endif
     339             : };
     340             : 
     341             : } // dom namespace
     342             : } // mozilla namespace
     343             : 
     344             : #endif // mozilla_dom_StructuredCloneHolder_h

Generated by: LCOV version 1.13