dom/ipc/Blob.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "Blob.h"
     7 #include "ContentChild.h"
     8 #include "ContentParent.h"
     9 #include "FileDescriptorSetChild.h"
    10 #include "jsapi.h"
    11 #include "mozilla/Assertions.h"
    12 #include "mozilla/DebugOnly.h"
    13 #include "mozilla/Monitor.h"
    14 #include "mozilla/unused.h"
    15 #include "mozilla/dom/PBlobStreamChild.h"
    16 #include "mozilla/dom/PBlobStreamParent.h"
    17 #include "mozilla/dom/PFileDescriptorSetParent.h"
    18 #include "mozilla/ipc/InputStreamUtils.h"
    19 #include "nsCOMPtr.h"
    20 #include "nsDOMFile.h"
    21 #include "nsIDOMFile.h"
    22 #include "nsIInputStream.h"
    23 #include "nsIIPCSerializableInputStream.h"
    24 #include "nsIMultiplexInputStream.h"
    25 #include "nsIRemoteBlob.h"
    26 #include "nsISeekableStream.h"
    27 #include "nsNetCID.h"
    28 #include "nsProxyRelease.h"
    29 #include "nsThreadUtils.h"
    31 #define PRIVATE_REMOTE_INPUT_STREAM_IID \
    32   {0x30c7699f, 0x51d2, 0x48c8, {0xad, 0x56, 0xc0, 0x16, 0xd7, 0x6f, 0x71, 0x27}}
    34 using namespace mozilla;
    35 using namespace mozilla::dom;
    36 using namespace mozilla::ipc;
    38 namespace {
    40 enum ActorType
    41 {
    42   ChildActor,
    43   ParentActor
    44 };
    46 // Ensure that a nsCOMPtr/nsRefPtr is released on the main thread.
    47 template <template <class> class SmartPtr, class T>
    48 void
    49 ProxyReleaseToMainThread(SmartPtr<T>& aDoomed)
    50 {
    51   MOZ_ASSERT(!NS_IsMainThread());
    53   nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
    54   NS_ENSURE_TRUE_VOID(mainThread);
    56   if (NS_FAILED(NS_ProxyRelease(mainThread, aDoomed, true))) {
    57     NS_WARNING("Failed to proxy release to main thread!");
    58   }
    59 }
    61 class NS_NO_VTABLE IPrivateRemoteInputStream : public nsISupports
    62 {
    63 public:
    64   NS_DECLARE_STATIC_IID_ACCESSOR(PRIVATE_REMOTE_INPUT_STREAM_IID)
    66   // This will return the underlying stream.
    67   virtual nsIInputStream*
    68   BlockAndGetInternalStream() = 0;
    69 };
    71 NS_DEFINE_STATIC_IID_ACCESSOR(IPrivateRemoteInputStream,
    72                               PRIVATE_REMOTE_INPUT_STREAM_IID)
    74 // This class exists to keep a blob alive at least as long as its internal
    75 // stream.
    76 class BlobInputStreamTether : public nsIMultiplexInputStream,
    77                               public nsISeekableStream,
    78                               public nsIIPCSerializableInputStream
    79 {
    80   nsCOMPtr<nsIInputStream> mStream;
    81   nsCOMPtr<nsIDOMBlob> mSourceBlob;
    83   nsIMultiplexInputStream* mWeakMultiplexStream;
    84   nsISeekableStream* mWeakSeekableStream;
    85   nsIIPCSerializableInputStream* mWeakSerializableStream;
    87 public:
    88   NS_DECL_THREADSAFE_ISUPPORTS
    89   NS_FORWARD_NSIINPUTSTREAM(mStream->)
    90   NS_FORWARD_SAFE_NSIMULTIPLEXINPUTSTREAM(mWeakMultiplexStream)
    91   NS_FORWARD_SAFE_NSISEEKABLESTREAM(mWeakSeekableStream)
    92   NS_FORWARD_SAFE_NSIIPCSERIALIZABLEINPUTSTREAM(mWeakSerializableStream)
    94   BlobInputStreamTether(nsIInputStream* aStream, nsIDOMBlob* aSourceBlob)
    95   : mStream(aStream), mSourceBlob(aSourceBlob), mWeakMultiplexStream(nullptr),
    96     mWeakSeekableStream(nullptr), mWeakSerializableStream(nullptr)
    97   {
    98     MOZ_ASSERT(aStream);
    99     MOZ_ASSERT(aSourceBlob);
   101     nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
   102       do_QueryInterface(aStream);
   103     if (multiplexStream) {
   104       MOZ_ASSERT(SameCOMIdentity(aStream, multiplexStream));
   105       mWeakMultiplexStream = multiplexStream;
   106     }
   108     nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
   109     if (seekableStream) {
   110       MOZ_ASSERT(SameCOMIdentity(aStream, seekableStream));
   111       mWeakSeekableStream = seekableStream;
   112     }
   114     nsCOMPtr<nsIIPCSerializableInputStream> serializableStream =
   115       do_QueryInterface(aStream);
   116     if (serializableStream) {
   117       MOZ_ASSERT(SameCOMIdentity(aStream, serializableStream));
   118       mWeakSerializableStream = serializableStream;
   119     }
   120   }
   122 protected:
   123   virtual ~BlobInputStreamTether()
   124   {
   125     MOZ_ASSERT(mStream);
   126     MOZ_ASSERT(mSourceBlob);
   128     if (!NS_IsMainThread()) {
   129       mStream = nullptr;
   130       ProxyReleaseToMainThread(mSourceBlob);
   131     }
   132   }
   133 };
   135 NS_IMPL_ADDREF(BlobInputStreamTether)
   136 NS_IMPL_RELEASE(BlobInputStreamTether)
   138 NS_INTERFACE_MAP_BEGIN(BlobInputStreamTether)
   139   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   140   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMultiplexInputStream,
   141                                      mWeakMultiplexStream)
   142   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mWeakSeekableStream)
   143   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
   144                                      mWeakSerializableStream)
   145   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
   146 NS_INTERFACE_MAP_END
   148 class RemoteInputStream : public nsIInputStream,
   149                           public nsISeekableStream,
   150                           public nsIIPCSerializableInputStream,
   151                           public IPrivateRemoteInputStream
   152 {
   153   mozilla::Monitor mMonitor;
   154   nsCOMPtr<nsIInputStream> mStream;
   155   nsCOMPtr<nsIDOMBlob> mSourceBlob;
   156   nsISeekableStream* mWeakSeekableStream;
   157   ActorType mOrigin;
   159 public:
   160   NS_DECL_THREADSAFE_ISUPPORTS
   162   RemoteInputStream(nsIDOMBlob* aSourceBlob, ActorType aOrigin)
   163   : mMonitor("RemoteInputStream.mMonitor"), mSourceBlob(aSourceBlob),
   164     mWeakSeekableStream(nullptr), mOrigin(aOrigin)
   165   {
   166     MOZ_ASSERT(NS_IsMainThread());
   167     MOZ_ASSERT(aSourceBlob);
   168   }
   170   void
   171   Serialize(InputStreamParams& aParams,
   172             FileDescriptorArray& /* aFileDescriptors */)
   173   {
   174     nsCOMPtr<nsIRemoteBlob> remote = do_QueryInterface(mSourceBlob);
   175     MOZ_ASSERT(remote);
   177     if (mOrigin == ParentActor) {
   178       aParams = RemoteInputStreamParams(
   179         static_cast<PBlobParent*>(remote->GetPBlob()), nullptr);
   180     } else {
   181       MOZ_ASSERT(mOrigin == ChildActor);
   182       aParams = RemoteInputStreamParams(
   183         nullptr, static_cast<PBlobChild*>(remote->GetPBlob()));
   184     }
   185   }
   187   bool
   188   Deserialize(const InputStreamParams& aParams,
   189               const FileDescriptorArray& /* aFileDescriptors */)
   190   {
   191     // See InputStreamUtils.cpp to see how deserialization of a
   192     // RemoteInputStream is special-cased.
   193     MOZ_CRASH("RemoteInputStream should never be deserialized");
   194   }
   196   void
   197   SetStream(nsIInputStream* aStream)
   198   {
   199     MOZ_ASSERT(NS_IsMainThread());
   200     MOZ_ASSERT(aStream);
   202     nsCOMPtr<nsIInputStream> stream = aStream;
   203     nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
   205     MOZ_ASSERT_IF(seekableStream, SameCOMIdentity(aStream, seekableStream));
   207     {
   208       mozilla::MonitorAutoLock lock(mMonitor);
   210       MOZ_ASSERT(!mStream);
   211       MOZ_ASSERT(!mWeakSeekableStream);
   213       mStream.swap(stream);
   214       mWeakSeekableStream = seekableStream;
   216       mMonitor.Notify();
   217     }
   218   }
   220   NS_IMETHOD
   221   Close() MOZ_OVERRIDE
   222   {
   223     nsresult rv = BlockAndWaitForStream();
   224     NS_ENSURE_SUCCESS(rv, rv);
   226     nsCOMPtr<nsIDOMBlob> sourceBlob;
   227     mSourceBlob.swap(sourceBlob);
   229     rv = mStream->Close();
   230     NS_ENSURE_SUCCESS(rv, rv);
   232     return NS_OK;
   233   }
   235   NS_IMETHOD
   236   Available(uint64_t* aAvailable) MOZ_OVERRIDE
   237   {
   238     // See large comment in FileInputStreamWrapper::Available.
   239     if (NS_IsMainThread()) {
   240       return NS_BASE_STREAM_CLOSED;
   241     }
   243     nsresult rv = BlockAndWaitForStream();
   244     NS_ENSURE_SUCCESS(rv, rv);
   246     rv = mStream->Available(aAvailable);
   247     NS_ENSURE_SUCCESS(rv, rv);
   249     return NS_OK;
   250   }
   252   NS_IMETHOD
   253   Read(char* aBuffer, uint32_t aCount, uint32_t* aResult) MOZ_OVERRIDE
   254   {
   255     nsresult rv = BlockAndWaitForStream();
   256     NS_ENSURE_SUCCESS(rv, rv);
   258     rv = mStream->Read(aBuffer, aCount, aResult);
   259     NS_ENSURE_SUCCESS(rv, rv);
   261     return NS_OK;
   262   }
   264   NS_IMETHOD
   265   ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
   266                uint32_t* aResult) MOZ_OVERRIDE
   267   {
   268     nsresult rv = BlockAndWaitForStream();
   269     NS_ENSURE_SUCCESS(rv, rv);
   271     rv = mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
   272     NS_ENSURE_SUCCESS(rv, rv);
   274     return NS_OK;
   275   }
   277   NS_IMETHOD
   278   IsNonBlocking(bool* aNonBlocking) MOZ_OVERRIDE
   279   {
   280     NS_ENSURE_ARG_POINTER(aNonBlocking);
   282     *aNonBlocking = false;
   283     return NS_OK;
   284   }
   286   NS_IMETHOD
   287   Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE
   288   {
   289     nsresult rv = BlockAndWaitForStream();
   290     NS_ENSURE_SUCCESS(rv, rv);
   292     if (!mWeakSeekableStream) {
   293       NS_WARNING("Underlying blob stream is not seekable!");
   294       return NS_ERROR_NO_INTERFACE;
   295     }
   297     rv = mWeakSeekableStream->Seek(aWhence, aOffset);
   298     NS_ENSURE_SUCCESS(rv, rv);
   300     return NS_OK;
   301   }
   303   NS_IMETHOD
   304   Tell(int64_t* aResult)
   305   {
   306     // We can cheat here and assume that we're going to start at 0 if we don't
   307     // yet have our stream. Though, really, this should abort since most input
   308     // streams could block here.
   309     if (NS_IsMainThread() && !mStream) {
   310       *aResult = 0;
   311       return NS_OK;
   312     }
   314     nsresult rv = BlockAndWaitForStream();
   315     NS_ENSURE_SUCCESS(rv, rv);
   317     if (!mWeakSeekableStream) {
   318       NS_WARNING("Underlying blob stream is not seekable!");
   319       return NS_ERROR_NO_INTERFACE;
   320     }
   322     rv = mWeakSeekableStream->Tell(aResult);
   323     NS_ENSURE_SUCCESS(rv, rv);
   325     return NS_OK;
   326   }
   328   NS_IMETHOD
   329   SetEOF()
   330   {
   331     nsresult rv = BlockAndWaitForStream();
   332     NS_ENSURE_SUCCESS(rv, rv);
   334     if (!mWeakSeekableStream) {
   335       NS_WARNING("Underlying blob stream is not seekable!");
   336       return NS_ERROR_NO_INTERFACE;
   337     }
   339     rv = mWeakSeekableStream->SetEOF();
   340     NS_ENSURE_SUCCESS(rv, rv);
   342     return NS_OK;
   343   }
   345   virtual nsIInputStream*
   346   BlockAndGetInternalStream()
   347   {
   348     MOZ_ASSERT(!NS_IsMainThread());
   350     nsresult rv = BlockAndWaitForStream();
   351     NS_ENSURE_SUCCESS(rv, nullptr);
   353     return mStream;
   354   }
   356 private:
   357   virtual ~RemoteInputStream()
   358   {
   359     if (!NS_IsMainThread()) {
   360       mStream = nullptr;
   361       mWeakSeekableStream = nullptr;
   362       ProxyReleaseToMainThread(mSourceBlob);
   363     }
   364   }
   366   void
   367   ReallyBlockAndWaitForStream()
   368   {
   369     mozilla::DebugOnly<bool> waited;
   371     {
   372       mozilla::MonitorAutoLock lock(mMonitor);
   374       waited = !mStream;
   376       while (!mStream) {
   377         mMonitor.Wait();
   378       }
   379     }
   381     MOZ_ASSERT(mStream);
   383 #ifdef DEBUG
   384     if (waited && mWeakSeekableStream) {
   385       int64_t position;
   386       MOZ_ASSERT(NS_SUCCEEDED(mWeakSeekableStream->Tell(&position)),
   387                  "Failed to determine initial stream position!");
   388       MOZ_ASSERT(!position, "Stream not starting at 0!");
   389     }
   390 #endif
   391   }
   393   nsresult
   394   BlockAndWaitForStream()
   395   {
   396     if (NS_IsMainThread()) {
   397       NS_WARNING("Blocking the main thread is not supported!");
   398       return NS_ERROR_FAILURE;
   399     }
   401     ReallyBlockAndWaitForStream();
   403     return NS_OK;
   404   }
   406   bool
   407   IsSeekableStream()
   408   {
   409     if (NS_IsMainThread()) {
   410       if (!mStream) {
   411         NS_WARNING("Don't know if this stream is seekable yet!");
   412         return true;
   413       }
   414     }
   415     else {
   416       ReallyBlockAndWaitForStream();
   417     }
   419     return !!mWeakSeekableStream;
   420   }
   421 };
   423 NS_IMPL_ADDREF(RemoteInputStream)
   424 NS_IMPL_RELEASE(RemoteInputStream)
   426 NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
   427   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   428   NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
   429   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
   430   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
   431   NS_INTERFACE_MAP_ENTRY(IPrivateRemoteInputStream)
   432 NS_INTERFACE_MAP_END
   434 class InputStreamChild MOZ_FINAL
   435   : public PBlobStreamChild
   436 {
   437   nsRefPtr<RemoteInputStream> mRemoteStream;
   439 public:
   440   InputStreamChild(RemoteInputStream* aRemoteStream)
   441   : mRemoteStream(aRemoteStream)
   442   {
   443     MOZ_ASSERT(NS_IsMainThread());
   444     MOZ_ASSERT(aRemoteStream);
   445   }
   447   InputStreamChild()
   448   {
   449     MOZ_ASSERT(NS_IsMainThread());
   450   }
   452 private:
   453   // This method is only called by the IPDL message machinery.
   454   virtual bool
   455   Recv__delete__(const InputStreamParams& aParams,
   456                  const OptionalFileDescriptorSet& aFDs) MOZ_OVERRIDE;
   457 };
   459 class InputStreamParent MOZ_FINAL
   460   : public PBlobStreamParent
   461 {
   462   nsRefPtr<RemoteInputStream> mRemoteStream;
   464 public:
   465   InputStreamParent(RemoteInputStream* aRemoteStream)
   466   : mRemoteStream(aRemoteStream)
   467   {
   468     MOZ_ASSERT(NS_IsMainThread());
   469     MOZ_ASSERT(aRemoteStream);
   470   }
   472   InputStreamParent()
   473   {
   474     MOZ_ASSERT(NS_IsMainThread());
   475   }
   477 private:
   478   // This method is only called by the IPDL message machinery.
   479   virtual bool
   480   Recv__delete__(const InputStreamParams& aParams,
   481                  const OptionalFileDescriptorSet& aFDs) MOZ_OVERRIDE;
   482 };
   484 nsDOMFileBase*
   485 ToConcreteBlob(nsIDOMBlob* aBlob)
   486 {
   487   // XXX This is only safe so long as all blob implementations in our tree
   488   //     inherit nsDOMFileBase. If that ever changes then this will need to grow
   489   //     a real interface or something.
   490   return static_cast<nsDOMFileBase*>(aBlob);
   491 }
   493 } // anonymous namespace
   495 // Each instance of this class will be dispatched to the network stream thread
   496 // pool to run the first time where it will open the file input stream. It will
   497 // then dispatch itself back to the main thread to send the child process its
   498 // response (assuming that the child has not crashed). The runnable will then
   499 // dispatch itself to the thread pool again in order to close the file input
   500 // stream.
   501 class BlobParent::OpenStreamRunnable MOZ_FINAL
   502   : public nsRunnable
   503 {
   504   friend class nsRevocableEventPtr<OpenStreamRunnable>;
   506   // Only safe to access these pointers if mRevoked is false!
   507   BlobParent* mBlobActor;
   508   PBlobStreamParent* mStreamActor;
   510   nsCOMPtr<nsIInputStream> mStream;
   511   nsCOMPtr<nsIIPCSerializableInputStream> mSerializable;
   512   nsCOMPtr<nsIEventTarget> mTarget;
   514   bool mRevoked;
   515   bool mClosing;
   517 public:
   518   OpenStreamRunnable(BlobParent* aBlobActor,
   519                      PBlobStreamParent* aStreamActor,
   520                      nsIInputStream* aStream,
   521                      nsIIPCSerializableInputStream* aSerializable,
   522                      nsIEventTarget* aTarget)
   523   : mBlobActor(aBlobActor), mStreamActor(aStreamActor), mStream(aStream),
   524     mSerializable(aSerializable), mTarget(aTarget), mRevoked(false),
   525     mClosing(false)
   526   {
   527     MOZ_ASSERT(NS_IsMainThread());
   528     MOZ_ASSERT(aBlobActor);
   529     MOZ_ASSERT(aStreamActor);
   530     MOZ_ASSERT(aStream);
   531     // aSerializable may be null.
   532     MOZ_ASSERT(aTarget);
   533   }
   535   NS_IMETHOD
   536   Run()
   537   {
   538     if (NS_IsMainThread()) {
   539       return SendResponse();
   540     }
   542     if (!mClosing) {
   543       return OpenStream();
   544     }
   546     return CloseStream();
   547   }
   549   nsresult
   550   Dispatch()
   551   {
   552     MOZ_ASSERT(NS_IsMainThread());
   553     MOZ_ASSERT(mTarget);
   555     nsresult rv = mTarget->Dispatch(this, NS_DISPATCH_NORMAL);
   556     NS_ENSURE_SUCCESS(rv, rv);
   558     return NS_OK;
   559   }
   561 private:
   562   void
   563   Revoke()
   564   {
   565     MOZ_ASSERT(NS_IsMainThread());
   566 #ifdef DEBUG
   567     mBlobActor = nullptr;
   568     mStreamActor = nullptr;
   569 #endif
   570     mRevoked = true;
   571   }
   573   nsresult
   574   OpenStream()
   575   {
   576     MOZ_ASSERT(!NS_IsMainThread());
   577     MOZ_ASSERT(mStream);
   579     if (!mSerializable) {
   580       nsCOMPtr<IPrivateRemoteInputStream> remoteStream =
   581         do_QueryInterface(mStream);
   582       MOZ_ASSERT(remoteStream, "Must QI to IPrivateRemoteInputStream here!");
   584       nsCOMPtr<nsIInputStream> realStream =
   585         remoteStream->BlockAndGetInternalStream();
   586       NS_ENSURE_TRUE(realStream, NS_ERROR_FAILURE);
   588       mSerializable = do_QueryInterface(realStream);
   589       if (!mSerializable) {
   590         MOZ_ASSERT(false, "Must be serializable!");
   591         return NS_ERROR_FAILURE;
   592       }
   594       mStream.swap(realStream);
   595     }
   597     // To force the stream open we call Available(). We don't actually care
   598     // how much data is available.
   599     uint64_t available;
   600     if (NS_FAILED(mStream->Available(&available))) {
   601       NS_WARNING("Available failed on this stream!");
   602     }
   604     nsresult rv = NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
   605     NS_ENSURE_SUCCESS(rv, rv);
   607     return NS_OK;
   608   }
   610   nsresult
   611   CloseStream()
   612   {
   613     MOZ_ASSERT(!NS_IsMainThread());
   614     MOZ_ASSERT(mStream);
   616     // Going to always release here.
   617     nsCOMPtr<nsIInputStream> stream;
   618     mStream.swap(stream);
   620     nsresult rv = stream->Close();
   621     NS_ENSURE_SUCCESS(rv, rv);
   623     return NS_OK;
   624   }
   626   nsresult
   627   SendResponse()
   628   {
   629     MOZ_ASSERT(NS_IsMainThread());
   631     MOZ_ASSERT(mStream);
   632     MOZ_ASSERT(mSerializable);
   633     MOZ_ASSERT(mTarget);
   634     MOZ_ASSERT(!mClosing);
   636     nsCOMPtr<nsIIPCSerializableInputStream> serializable;
   637     mSerializable.swap(serializable);
   639     if (mRevoked) {
   640       MOZ_ASSERT(!mBlobActor);
   641       MOZ_ASSERT(!mStreamActor);
   642     }
   643     else {
   644       MOZ_ASSERT(mBlobActor);
   645       MOZ_ASSERT(mStreamActor);
   647       InputStreamParams params;
   648       nsAutoTArray<FileDescriptor, 10> fds;
   649       serializable->Serialize(params, fds);
   651       MOZ_ASSERT(params.type() != InputStreamParams::T__None);
   653       PFileDescriptorSetParent* fdSet = nullptr;
   655       if (!fds.IsEmpty()) {
   656         auto* manager = static_cast<ContentParent*>(mBlobActor->Manager());
   657         MOZ_ASSERT(manager);
   659         fdSet = manager->SendPFileDescriptorSetConstructor(fds[0]);
   660         if (fdSet) {
   661           for (uint32_t index = 1; index < fds.Length(); index++) {
   662             unused << fdSet->SendAddFileDescriptor(fds[index]);
   663           }
   664         }
   665       }
   667       OptionalFileDescriptorSet optionalFDs;
   668       if (fdSet) {
   669         optionalFDs = fdSet;
   670       } else {
   671         optionalFDs = mozilla::void_t();
   672       }
   674       unused <<
   675         PBlobStreamParent::Send__delete__(mStreamActor, params, optionalFDs);
   677       mBlobActor->NoteRunnableCompleted(this);
   679 #ifdef DEBUG
   680       mBlobActor = nullptr;
   681       mStreamActor = nullptr;
   682 #endif
   683     }
   685     mClosing = true;
   687     nsCOMPtr<nsIEventTarget> target;
   688     mTarget.swap(target);
   690     nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
   691     NS_ENSURE_SUCCESS(rv, rv);
   693     return NS_OK;
   694   }
   695 };
   697 /*******************************************************************************
   698  * BlobChild::RemoteBlob Declaration
   699  ******************************************************************************/
   701 class BlobChild::RemoteBlob MOZ_FINAL
   702   : public nsDOMFile
   703   , public nsIRemoteBlob
   704 {
   705   class StreamHelper;
   706   class SliceHelper;
   708   BlobChild* mActor;
   710 public:
   711   RemoteBlob(const nsAString& aName,
   712              const nsAString& aContentType,
   713              uint64_t aLength,
   714              uint64_t aModDate)
   715     : nsDOMFile(aName, aContentType, aLength, aModDate)
   716     , mActor(nullptr)
   717   {
   718     mImmutable = true;
   719   }
   721   RemoteBlob(const nsAString& aContentType, uint64_t aLength)
   722     : nsDOMFile(aContentType, aLength)
   723     , mActor(nullptr)
   724   {
   725     mImmutable = true;
   726   }
   728   RemoteBlob()
   729     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
   730     , mActor(nullptr)
   731   {
   732     mImmutable = true;
   733   }
   735   void
   736   SetActor(BlobChild* aActor)
   737   {
   738     MOZ_ASSERT(!aActor || !mActor);
   739     mActor = aActor;
   740   }
   742   NS_DECL_ISUPPORTS_INHERITED
   744   virtual already_AddRefed<nsIDOMBlob>
   745   CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType)
   746               MOZ_OVERRIDE;
   748   NS_IMETHOD
   749   GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
   751   NS_IMETHOD
   752   GetLastModifiedDate(JSContext* cx,
   753                       JS::MutableHandle<JS::Value> aLastModifiedDate)
   754                       MOZ_OVERRIDE;
   756   virtual void*
   757   GetPBlob() MOZ_OVERRIDE;
   759 private:
   760   ~RemoteBlob()
   761   {
   762     if (mActor) {
   763       mActor->NoteDyingRemoteBlob();
   764     }
   765   }
   766 };
   768 class BlobChild::RemoteBlob::StreamHelper MOZ_FINAL
   769   : public nsRunnable
   770 {
   771   mozilla::Monitor mMonitor;
   772   BlobChild* mActor;
   773   nsCOMPtr<nsIDOMBlob> mSourceBlob;
   774   nsRefPtr<RemoteInputStream> mInputStream;
   775   bool mDone;
   777 public:
   778   StreamHelper(BlobChild* aActor, nsIDOMBlob* aSourceBlob)
   779     : mMonitor("BlobChild::RemoteBlob::StreamHelper::mMonitor")
   780     , mActor(aActor)
   781     , mSourceBlob(aSourceBlob)
   782     , mDone(false)
   783   {
   784     // This may be created on any thread.
   785     MOZ_ASSERT(aActor);
   786     MOZ_ASSERT(aSourceBlob);
   787   }
   789   nsresult
   790   GetStream(nsIInputStream** aInputStream)
   791   {
   792     // This may be called on any thread.
   793     MOZ_ASSERT(aInputStream);
   794     MOZ_ASSERT(mActor);
   795     MOZ_ASSERT(!mInputStream);
   796     MOZ_ASSERT(!mDone);
   798     if (NS_IsMainThread()) {
   799       RunInternal(false);
   800     }
   801     else {
   802       nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
   803       NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
   805       nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
   806       NS_ENSURE_SUCCESS(rv, rv);
   808       {
   809         MonitorAutoLock lock(mMonitor);
   810         while (!mDone) {
   811           lock.Wait();
   812         }
   813       }
   814     }
   816     MOZ_ASSERT(!mActor);
   817     MOZ_ASSERT(mDone);
   819     if (!mInputStream) {
   820       return NS_ERROR_UNEXPECTED;
   821     }
   823     mInputStream.forget(aInputStream);
   824     return NS_OK;
   825   }
   827   NS_IMETHOD
   828   Run()
   829   {
   830     MOZ_ASSERT(NS_IsMainThread());
   831     RunInternal(true);
   832     return NS_OK;
   833   }
   835 private:
   836   void
   837   RunInternal(bool aNotify)
   838   {
   839     MOZ_ASSERT(NS_IsMainThread());
   840     MOZ_ASSERT(mActor);
   841     MOZ_ASSERT(!mInputStream);
   842     MOZ_ASSERT(!mDone);
   844     nsRefPtr<RemoteInputStream> stream =
   845       new RemoteInputStream(mSourceBlob, ChildActor);
   847     InputStreamChild* streamActor = new InputStreamChild(stream);
   848     if (mActor->SendPBlobStreamConstructor(streamActor)) {
   849       stream.swap(mInputStream);
   850     }
   852     mActor = nullptr;
   854     if (aNotify) {
   855       MonitorAutoLock lock(mMonitor);
   856       mDone = true;
   857       lock.Notify();
   858     }
   859     else {
   860       mDone = true;
   861     }
   862   }
   863 };
   865 class BlobChild::RemoteBlob::SliceHelper MOZ_FINAL
   866   : public nsRunnable
   867 {
   868   mozilla::Monitor mMonitor;
   869   BlobChild* mActor;
   870   nsCOMPtr<nsIDOMBlob> mSlice;
   871   uint64_t mStart;
   872   uint64_t mLength;
   873   nsString mContentType;
   874   bool mDone;
   876 public:
   877   SliceHelper(BlobChild* aActor)
   878     : mMonitor("BlobChild::RemoteBlob::SliceHelper::mMonitor")
   879     , mActor(aActor)
   880     , mStart(0)
   881     , mLength(0)
   882     , mDone(false)
   883   {
   884     // This may be created on any thread.
   885     MOZ_ASSERT(aActor);
   886   }
   888   nsresult
   889   GetSlice(uint64_t aStart,
   890            uint64_t aLength,
   891            const nsAString& aContentType,
   892            nsIDOMBlob** aSlice)
   893   {
   894     // This may be called on any thread.
   895     MOZ_ASSERT(aSlice);
   896     MOZ_ASSERT(mActor);
   897     MOZ_ASSERT(!mSlice);
   898     MOZ_ASSERT(!mDone);
   900     mStart = aStart;
   901     mLength = aLength;
   902     mContentType = aContentType;
   904     if (NS_IsMainThread()) {
   905       RunInternal(false);
   906     }
   907     else {
   908       nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
   909       NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
   911       nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
   912       NS_ENSURE_SUCCESS(rv, rv);
   914       {
   915         MonitorAutoLock lock(mMonitor);
   916         while (!mDone) {
   917           lock.Wait();
   918         }
   919       }
   920     }
   922     MOZ_ASSERT(!mActor);
   923     MOZ_ASSERT(mDone);
   925     if (!mSlice) {
   926       return NS_ERROR_UNEXPECTED;
   927     }
   929     mSlice.forget(aSlice);
   930     return NS_OK;
   931   }
   933   NS_IMETHOD
   934   Run()
   935   {
   936     MOZ_ASSERT(NS_IsMainThread());
   937     RunInternal(true);
   938     return NS_OK;
   939   }
   941 private:
   942   void
   943   RunInternal(bool aNotify)
   944   {
   945     MOZ_ASSERT(NS_IsMainThread());
   946     MOZ_ASSERT(mActor);
   947     MOZ_ASSERT(!mSlice);
   948     MOZ_ASSERT(!mDone);
   950     NS_ENSURE_TRUE_VOID(mActor->Manager());
   952     NormalBlobConstructorParams normalParams;
   953     normalParams.contentType() = mContentType;
   954     normalParams.length() = mLength;
   956     auto* manager = static_cast<ContentChild*>(mActor->Manager());
   957     MOZ_ASSERT(manager);
   959     BlobChild* newActor = BlobChild::Create(manager, normalParams);
   960     MOZ_ASSERT(newActor);
   962     SlicedBlobConstructorParams slicedParams;
   963     slicedParams.contentType() = mContentType;
   964     slicedParams.begin() = mStart;
   965     slicedParams.end() = mStart + mLength;
   966     slicedParams.sourceChild() = mActor;
   968     ParentBlobConstructorParams otherSideParams;
   969     otherSideParams.blobParams() = slicedParams;
   970     otherSideParams.optionalInputStreamParams() = mozilla::void_t();
   972     if (mActor->Manager()->SendPBlobConstructor(newActor, otherSideParams)) {
   973       mSlice = newActor->GetBlob();
   974     }
   976     mActor = nullptr;
   978     if (aNotify) {
   979       MonitorAutoLock lock(mMonitor);
   980       mDone = true;
   981       lock.Notify();
   982     }
   983     else {
   984       mDone = true;
   985     }
   986   }
   987 };
   989 /*******************************************************************************
   990  * BlobChild::RemoteBlob Implementation
   991  ******************************************************************************/
   993 NS_IMPL_ISUPPORTS_INHERITED(BlobChild::RemoteBlob, nsDOMFile, nsIRemoteBlob)
   995 already_AddRefed<nsIDOMBlob>
   996 BlobChild::
   997 RemoteBlob::CreateSlice(uint64_t aStart,
   998                         uint64_t aLength,
   999                         const nsAString& aContentType)
  1001   if (!mActor) {
  1002     return nullptr;
  1005   nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
  1007   nsCOMPtr<nsIDOMBlob> slice;
  1008   nsresult rv =
  1009     helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
  1010   NS_ENSURE_SUCCESS(rv, nullptr);
  1012   return slice.forget();
  1015 NS_IMETHODIMP
  1016 BlobChild::
  1017 RemoteBlob::GetInternalStream(nsIInputStream** aStream)
  1019   if (!mActor) {
  1020     return NS_ERROR_UNEXPECTED;
  1023   nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
  1024   return helper->GetStream(aStream);
  1027 NS_IMETHODIMP
  1028 BlobChild::
  1029 RemoteBlob::GetLastModifiedDate(JSContext* cx,
  1030                                 JS::MutableHandle<JS::Value> aLastModifiedDate)
  1032   if (IsDateUnknown()) {
  1033     aLastModifiedDate.setNull();
  1034   } else {
  1035     JSObject* date = JS_NewDateObjectMsec(cx, mLastModificationDate);
  1036     if (!date) {
  1037       return NS_ERROR_OUT_OF_MEMORY;
  1039     aLastModifiedDate.setObject(*date);
  1041   return NS_OK;
  1044 void*
  1045 BlobChild::
  1046 RemoteBlob::GetPBlob()
  1048   return static_cast<PBlobChild*>(mActor);
  1051 /*******************************************************************************
  1052  * BlobChild
  1053  ******************************************************************************/
  1055 BlobChild::BlobChild(ContentChild* aManager, nsIDOMBlob* aBlob)
  1056   : mBlob(aBlob)
  1057   , mRemoteBlob(nullptr)
  1058   , mStrongManager(aManager)
  1059   , mOwnsBlob(true)
  1060   , mBlobIsFile(false)
  1062   MOZ_ASSERT(NS_IsMainThread());
  1063   MOZ_ASSERT(aManager);
  1064   MOZ_ASSERT(aBlob);
  1066   aBlob->AddRef();
  1068   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
  1069   mBlobIsFile = !!file;
  1072 BlobChild::BlobChild(ContentChild* aManager,
  1073                      const ChildBlobConstructorParams& aParams)
  1074   : mBlob(nullptr)
  1075   , mRemoteBlob(nullptr)
  1076   , mStrongManager(aManager)
  1077   , mOwnsBlob(false)
  1078   , mBlobIsFile(false)
  1080   MOZ_ASSERT(NS_IsMainThread());
  1081   MOZ_ASSERT(aManager);
  1083   ChildBlobConstructorParams::Type paramsType = aParams.type();
  1085   mBlobIsFile =
  1086     paramsType == ChildBlobConstructorParams::TFileBlobConstructorParams ||
  1087     paramsType == ChildBlobConstructorParams::TMysteryBlobConstructorParams;
  1089   nsRefPtr<RemoteBlob> remoteBlob = CreateRemoteBlob(aParams);
  1090   MOZ_ASSERT(remoteBlob);
  1092   remoteBlob->SetActor(this);
  1093   remoteBlob.forget(&mRemoteBlob);
  1095   mBlob = mRemoteBlob;
  1096   mOwnsBlob = true;
  1099 BlobChild::~BlobChild()
  1103 BlobChild*
  1104 BlobChild::Create(ContentChild* aManager,
  1105                   const ChildBlobConstructorParams& aParams)
  1107   MOZ_ASSERT(NS_IsMainThread());
  1108   MOZ_ASSERT(aManager);
  1110   switch (aParams.type()) {
  1111     case ChildBlobConstructorParams::TNormalBlobConstructorParams:
  1112     case ChildBlobConstructorParams::TFileBlobConstructorParams:
  1113     case ChildBlobConstructorParams::TMysteryBlobConstructorParams:
  1114       return new BlobChild(aManager, aParams);
  1116     case ChildBlobConstructorParams::TSlicedBlobConstructorParams: {
  1117       const SlicedBlobConstructorParams& params =
  1118         aParams.get_SlicedBlobConstructorParams();
  1120       auto* actor =
  1121         const_cast<BlobChild*>(
  1122           static_cast<const BlobChild*>(params.sourceChild()));
  1123       MOZ_ASSERT(actor);
  1125       nsCOMPtr<nsIDOMBlob> source = actor->GetBlob();
  1126       MOZ_ASSERT(source);
  1128       nsCOMPtr<nsIDOMBlob> slice;
  1129       nsresult rv =
  1130         source->Slice(params.begin(), params.end(), params.contentType(), 3,
  1131                       getter_AddRefs(slice));
  1132       NS_ENSURE_SUCCESS(rv, nullptr);
  1134       return new BlobChild(aManager, slice);
  1137     default:
  1138       MOZ_CRASH("Unknown params!");
  1141   return nullptr;
  1144 already_AddRefed<nsIDOMBlob>
  1145 BlobChild::GetBlob()
  1147   MOZ_ASSERT(NS_IsMainThread());
  1148   MOZ_ASSERT(mBlob);
  1150   nsCOMPtr<nsIDOMBlob> blob;
  1152   // Remote blobs are held alive until the first call to GetBlob. Thereafter we
  1153   // only hold a weak reference. Normal blobs are held alive until the actor is
  1154   // destroyed.
  1155   if (mRemoteBlob && mOwnsBlob) {
  1156     blob = dont_AddRef(mBlob);
  1157     mOwnsBlob = false;
  1159   else {
  1160     blob = mBlob;
  1163   MOZ_ASSERT(blob);
  1165   return blob.forget();
  1168 bool
  1169 BlobChild::SetMysteryBlobInfo(const nsString& aName,
  1170                               const nsString& aContentType,
  1171                               uint64_t aLength,
  1172                               uint64_t aLastModifiedDate)
  1174   MOZ_ASSERT(NS_IsMainThread());
  1175   MOZ_ASSERT(mBlob);
  1176   MOZ_ASSERT(mRemoteBlob);
  1177   MOZ_ASSERT(aLastModifiedDate != UINT64_MAX);
  1179   ToConcreteBlob(mBlob)->SetLazyData(aName, aContentType, aLength,
  1180                                      aLastModifiedDate);
  1182   FileBlobConstructorParams params(aName, aContentType, aLength,
  1183                                    aLastModifiedDate);
  1184   return SendResolveMystery(params);
  1187 bool
  1188 BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
  1190   MOZ_ASSERT(NS_IsMainThread());
  1191   MOZ_ASSERT(mBlob);
  1192   MOZ_ASSERT(mRemoteBlob);
  1194   nsString voidString;
  1195   voidString.SetIsVoid(true);
  1197   ToConcreteBlob(mBlob)->SetLazyData(voidString, aContentType, aLength,
  1198                                      UINT64_MAX);
  1200   NormalBlobConstructorParams params(aContentType, aLength);
  1201   return SendResolveMystery(params);
  1204 already_AddRefed<BlobChild::RemoteBlob>
  1205 BlobChild::CreateRemoteBlob(const ChildBlobConstructorParams& aParams)
  1207   MOZ_ASSERT(NS_IsMainThread());
  1209   nsRefPtr<RemoteBlob> remoteBlob;
  1211   switch (aParams.type()) {
  1212     case ChildBlobConstructorParams::TNormalBlobConstructorParams: {
  1213       const NormalBlobConstructorParams& params =
  1214         aParams.get_NormalBlobConstructorParams();
  1215       remoteBlob = new RemoteBlob(params.contentType(), params.length());
  1216       break;
  1219     case ChildBlobConstructorParams::TFileBlobConstructorParams: {
  1220       const FileBlobConstructorParams& params =
  1221         aParams.get_FileBlobConstructorParams();
  1222       remoteBlob =
  1223         new RemoteBlob(params.name(), params.contentType(), params.length(),
  1224                        params.modDate());
  1225       break;
  1228     case ChildBlobConstructorParams::TMysteryBlobConstructorParams: {
  1229       remoteBlob = new RemoteBlob();
  1230       break;
  1233     default:
  1234       MOZ_CRASH("Unknown params!");
  1237   MOZ_ASSERT(remoteBlob);
  1239   if (NS_FAILED(remoteBlob->SetMutable(false))) {
  1240     MOZ_CRASH("Failed to make remote blob immutable!");
  1243   return remoteBlob.forget();
  1246 void
  1247 BlobChild::NoteDyingRemoteBlob()
  1249   MOZ_ASSERT(mBlob);
  1250   MOZ_ASSERT(mRemoteBlob);
  1251   MOZ_ASSERT(!mOwnsBlob);
  1253   // This may be called on any thread due to the fact that RemoteBlob is
  1254   // designed to be passed between threads. We must start the shutdown process
  1255   // on the main thread, so we proxy here if necessary.
  1256   if (!NS_IsMainThread()) {
  1257     nsCOMPtr<nsIRunnable> runnable =
  1258       NS_NewNonOwningRunnableMethod(this, &BlobChild::NoteDyingRemoteBlob);
  1259     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
  1260       MOZ_ASSERT(false, "Should never fail!");
  1263     return;
  1266   // Must do this before calling Send__delete__ or we'll crash there trying to
  1267   // access a dangling pointer.
  1268   mBlob = nullptr;
  1269   mRemoteBlob = nullptr;
  1271   PBlobChild::Send__delete__(this);
  1274 void
  1275 BlobChild::ActorDestroy(ActorDestroyReason aWhy)
  1277   MOZ_ASSERT(NS_IsMainThread());
  1279   if (mRemoteBlob) {
  1280     mRemoteBlob->SetActor(nullptr);
  1283   if (mBlob && mOwnsBlob) {
  1284     mBlob->Release();
  1287   mStrongManager = nullptr;
  1290 PBlobStreamChild*
  1291 BlobChild::AllocPBlobStreamChild()
  1293   MOZ_ASSERT(NS_IsMainThread());
  1295   return new InputStreamChild();
  1298 bool
  1299 BlobChild::RecvPBlobStreamConstructor(PBlobStreamChild* aActor)
  1301   MOZ_ASSERT(NS_IsMainThread());
  1302   MOZ_ASSERT(aActor);
  1303   MOZ_ASSERT(mBlob);
  1304   MOZ_ASSERT(!mRemoteBlob);
  1306   nsCOMPtr<nsIInputStream> stream;
  1307   nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
  1308   NS_ENSURE_SUCCESS(rv, false);
  1310   nsCOMPtr<nsIIPCSerializableInputStream> serializable =
  1311     do_QueryInterface(stream);
  1312   if (!serializable) {
  1313     MOZ_ASSERT(false, "Must be serializable!");
  1314     return false;
  1317   InputStreamParams params;
  1318   nsTArray<FileDescriptor> fds;
  1319   serializable->Serialize(params, fds);
  1321   MOZ_ASSERT(params.type() != InputStreamParams::T__None);
  1322   MOZ_ASSERT(fds.IsEmpty());
  1324   return aActor->Send__delete__(aActor, params, mozilla::void_t());
  1327 bool
  1328 BlobChild::DeallocPBlobStreamChild(PBlobStreamChild* aActor)
  1330   MOZ_ASSERT(NS_IsMainThread());
  1332   delete static_cast<InputStreamChild*>(aActor);
  1333   return true;
  1336 bool
  1337 BlobChild::RecvResolveMystery(const ResolveMysteryParams& aParams)
  1339   MOZ_ASSERT(NS_IsMainThread());
  1340   MOZ_ASSERT(mBlob);
  1341   MOZ_ASSERT(!mRemoteBlob);
  1342   MOZ_ASSERT(mOwnsBlob);
  1344   if (!mBlobIsFile) {
  1345     MOZ_ASSERT(false, "Must always be a file!");
  1346     return false;
  1349   nsDOMFileBase* blob = ToConcreteBlob(mBlob);
  1351   switch (aParams.type()) {
  1352     case ResolveMysteryParams::TNormalBlobConstructorParams: {
  1353       const NormalBlobConstructorParams& params =
  1354         aParams.get_NormalBlobConstructorParams();
  1355       nsString voidString;
  1356       voidString.SetIsVoid(true);
  1357       blob->SetLazyData(voidString, params.contentType(), params.length(),
  1358                         UINT64_MAX);
  1359       break;
  1362     case ResolveMysteryParams::TFileBlobConstructorParams: {
  1363       const FileBlobConstructorParams& params =
  1364         aParams.get_FileBlobConstructorParams();
  1365       blob->SetLazyData(params.name(), params.contentType(), params.length(),
  1366                         params.modDate());
  1367       break;
  1370     default:
  1371       MOZ_CRASH("Unknown params!");
  1374   return true;
  1377 /*******************************************************************************
  1378  * BlobParent::RemoteBlob Declaration
  1379  ******************************************************************************/
  1381 class BlobParent::RemoteBlob MOZ_FINAL
  1382   : public nsDOMFile
  1383   , public nsIRemoteBlob
  1385   class StreamHelper;
  1386   class SliceHelper;
  1388   BlobParent* mActor;
  1389   InputStreamParams mInputStreamParams;
  1391 public:
  1392   RemoteBlob(const nsAString& aName,
  1393              const nsAString& aContentType,
  1394              uint64_t aLength,
  1395              uint64_t aModDate)
  1396     : nsDOMFile(aName, aContentType, aLength, aModDate)
  1397     , mActor(nullptr)
  1399     mImmutable = true;
  1402   RemoteBlob(const nsAString& aContentType, uint64_t aLength)
  1403     : nsDOMFile(aContentType, aLength)
  1404     , mActor(nullptr)
  1406     mImmutable = true;
  1409   RemoteBlob()
  1410     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
  1411     , mActor(nullptr)
  1413     mImmutable = true;
  1416   void
  1417   SetActor(BlobParent* aActor)
  1419     MOZ_ASSERT(!aActor || !mActor);
  1420     mActor = aActor;
  1423   void
  1424   MaybeSetInputStream(const ParentBlobConstructorParams& aParams)
  1426     if (aParams.optionalInputStreamParams().type() ==
  1427         OptionalInputStreamParams::TInputStreamParams) {
  1428       mInputStreamParams =
  1429         aParams.optionalInputStreamParams().get_InputStreamParams();
  1433   NS_DECL_ISUPPORTS_INHERITED
  1435   virtual already_AddRefed<nsIDOMBlob>
  1436   CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType)
  1437               MOZ_OVERRIDE;
  1439   NS_IMETHOD
  1440   GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
  1442   NS_IMETHOD
  1443   GetLastModifiedDate(JSContext* cx,
  1444                       JS::MutableHandle<JS::Value> aLastModifiedDate)
  1445                       MOZ_OVERRIDE;
  1447   virtual void*
  1448   GetPBlob() MOZ_OVERRIDE;
  1450 private:
  1451   ~RemoteBlob()
  1453     if (mActor) {
  1454       mActor->NoteDyingRemoteBlob();
  1457 };
  1459 class BlobParent::RemoteBlob::StreamHelper MOZ_FINAL
  1460   : public nsRunnable
  1462   mozilla::Monitor mMonitor;
  1463   BlobParent* mActor;
  1464   nsCOMPtr<nsIDOMBlob> mSourceBlob;
  1465   nsRefPtr<RemoteInputStream> mInputStream;
  1466   bool mDone;
  1468 public:
  1469   StreamHelper(BlobParent* aActor, nsIDOMBlob* aSourceBlob)
  1470     : mMonitor("BlobParent::RemoteBlob::StreamHelper::mMonitor")
  1471     , mActor(aActor)
  1472     , mSourceBlob(aSourceBlob)
  1473     , mDone(false)
  1475     // This may be created on any thread.
  1476     MOZ_ASSERT(aActor);
  1477     MOZ_ASSERT(aSourceBlob);
  1480   nsresult
  1481   GetStream(nsIInputStream** aInputStream)
  1483     // This may be called on any thread.
  1484     MOZ_ASSERT(aInputStream);
  1485     MOZ_ASSERT(mActor);
  1486     MOZ_ASSERT(!mInputStream);
  1487     MOZ_ASSERT(!mDone);
  1489     if (NS_IsMainThread()) {
  1490       RunInternal(false);
  1492     else {
  1493       nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
  1494       NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
  1496       nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
  1497       NS_ENSURE_SUCCESS(rv, rv);
  1500         MonitorAutoLock lock(mMonitor);
  1501         while (!mDone) {
  1502           lock.Wait();
  1507     MOZ_ASSERT(!mActor);
  1508     MOZ_ASSERT(mDone);
  1510     if (!mInputStream) {
  1511       return NS_ERROR_UNEXPECTED;
  1514     mInputStream.forget(aInputStream);
  1515     return NS_OK;
  1518   NS_IMETHOD
  1519   Run()
  1521     MOZ_ASSERT(NS_IsMainThread());
  1522     RunInternal(true);
  1523     return NS_OK;
  1526 private:
  1527   void
  1528   RunInternal(bool aNotify)
  1530     MOZ_ASSERT(NS_IsMainThread());
  1531     MOZ_ASSERT(mActor);
  1532     MOZ_ASSERT(!mInputStream);
  1533     MOZ_ASSERT(!mDone);
  1535     nsRefPtr<RemoteInputStream> stream =
  1536       new RemoteInputStream(mSourceBlob, ParentActor);
  1538     InputStreamParent* streamActor = new InputStreamParent(stream);
  1539     if (mActor->SendPBlobStreamConstructor(streamActor)) {
  1540       stream.swap(mInputStream);
  1543     mActor = nullptr;
  1545     if (aNotify) {
  1546       MonitorAutoLock lock(mMonitor);
  1547       mDone = true;
  1548       lock.Notify();
  1550     else {
  1551       mDone = true;
  1554 };
  1556 class BlobParent::RemoteBlob::SliceHelper MOZ_FINAL
  1557   : public nsRunnable
  1559   mozilla::Monitor mMonitor;
  1560   BlobParent* mActor;
  1561   nsCOMPtr<nsIDOMBlob> mSlice;
  1562   uint64_t mStart;
  1563   uint64_t mLength;
  1564   nsString mContentType;
  1565   bool mDone;
  1567 public:
  1568   SliceHelper(BlobParent* aActor)
  1569     : mMonitor("BlobParent::RemoteBlob::SliceHelper::mMonitor")
  1570     , mActor(aActor)
  1571     , mStart(0)
  1572     , mLength(0)
  1573     , mDone(false)
  1575     // This may be created on any thread.
  1576     MOZ_ASSERT(aActor);
  1579   nsresult
  1580   GetSlice(uint64_t aStart,
  1581            uint64_t aLength,
  1582            const nsAString& aContentType,
  1583            nsIDOMBlob** aSlice)
  1585     // This may be called on any thread.
  1586     MOZ_ASSERT(aSlice);
  1587     MOZ_ASSERT(mActor);
  1588     MOZ_ASSERT(!mSlice);
  1589     MOZ_ASSERT(!mDone);
  1591     mStart = aStart;
  1592     mLength = aLength;
  1593     mContentType = aContentType;
  1595     if (NS_IsMainThread()) {
  1596       RunInternal(false);
  1598     else {
  1599       nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
  1600       NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
  1602       nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
  1603       NS_ENSURE_SUCCESS(rv, rv);
  1606         MonitorAutoLock lock(mMonitor);
  1607         while (!mDone) {
  1608           lock.Wait();
  1613     MOZ_ASSERT(!mActor);
  1614     MOZ_ASSERT(mDone);
  1616     if (!mSlice) {
  1617       return NS_ERROR_UNEXPECTED;
  1620     mSlice.forget(aSlice);
  1621     return NS_OK;
  1624   NS_IMETHOD
  1625   Run()
  1627     MOZ_ASSERT(NS_IsMainThread());
  1628     RunInternal(true);
  1629     return NS_OK;
  1632 private:
  1633   void
  1634   RunInternal(bool aNotify)
  1636     MOZ_ASSERT(NS_IsMainThread());
  1637     MOZ_ASSERT(mActor);
  1638     MOZ_ASSERT(!mSlice);
  1639     MOZ_ASSERT(!mDone);
  1641     NS_ENSURE_TRUE_VOID(mActor->Manager());
  1643     NormalBlobConstructorParams normalParams;
  1644     normalParams.contentType() = mContentType;
  1645     normalParams.length() = mLength;
  1647     ParentBlobConstructorParams params;
  1648     params.blobParams() = normalParams;
  1649     params.optionalInputStreamParams() = void_t();
  1651     auto* manager = static_cast<ContentParent*>(mActor->Manager());
  1652     MOZ_ASSERT(manager);
  1654     BlobParent* newActor = BlobParent::Create(manager, params);
  1655     MOZ_ASSERT(newActor);
  1657     SlicedBlobConstructorParams slicedParams;
  1658     slicedParams.contentType() = mContentType;
  1659     slicedParams.begin() = mStart;
  1660     slicedParams.end() = mStart + mLength;
  1661     slicedParams.sourceParent() = mActor;
  1663     ChildBlobConstructorParams otherSideParams = slicedParams;
  1665     if (mActor->Manager()->SendPBlobConstructor(newActor, otherSideParams)) {
  1666       mSlice = newActor->GetBlob();
  1669     mActor = nullptr;
  1671     if (aNotify) {
  1672       MonitorAutoLock lock(mMonitor);
  1673       mDone = true;
  1674       lock.Notify();
  1676     else {
  1677       mDone = true;
  1680 };
  1682 /*******************************************************************************
  1683  * BlobChild::RemoteBlob Implementation
  1684  ******************************************************************************/
  1686 NS_IMPL_ISUPPORTS_INHERITED(BlobParent::RemoteBlob, nsDOMFile, nsIRemoteBlob)
  1688 already_AddRefed<nsIDOMBlob>
  1689 BlobParent::
  1690 RemoteBlob::CreateSlice(uint64_t aStart,
  1691                         uint64_t aLength,
  1692                         const nsAString& aContentType)
  1694   if (!mActor) {
  1695     return nullptr;
  1698   nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
  1700   nsCOMPtr<nsIDOMBlob> slice;
  1701   nsresult rv =
  1702     helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
  1703   NS_ENSURE_SUCCESS(rv, nullptr);
  1705   return slice.forget();
  1708 NS_IMETHODIMP
  1709 BlobParent::
  1710 RemoteBlob::GetInternalStream(nsIInputStream** aStream)
  1712   if (mInputStreamParams.type() != InputStreamParams::T__None) {
  1713     nsTArray<FileDescriptor> fds;
  1714     nsCOMPtr<nsIInputStream> realStream =
  1715       DeserializeInputStream(mInputStreamParams, fds);
  1716     if (!realStream) {
  1717       NS_WARNING("Failed to deserialize stream!");
  1718       return NS_ERROR_UNEXPECTED;
  1721     nsCOMPtr<nsIInputStream> stream =
  1722       new BlobInputStreamTether(realStream, this);
  1723     stream.forget(aStream);
  1724     return NS_OK;
  1727   if (!mActor) {
  1728     return NS_ERROR_UNEXPECTED;
  1731   nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
  1732   return helper->GetStream(aStream);
  1735 NS_IMETHODIMP
  1736 BlobParent::
  1737 RemoteBlob::GetLastModifiedDate(JSContext* cx,
  1738                                 JS::MutableHandle<JS::Value> aLastModifiedDate)
  1740   if (IsDateUnknown()) {
  1741     aLastModifiedDate.setNull();
  1742   } else {
  1743     JSObject* date = JS_NewDateObjectMsec(cx, mLastModificationDate);
  1744     if (!date) {
  1745       return NS_ERROR_OUT_OF_MEMORY;
  1747     aLastModifiedDate.setObject(*date);
  1749   return NS_OK;
  1752 void*
  1753 BlobParent::
  1754 RemoteBlob::GetPBlob()
  1756   return static_cast<PBlobParent*>(mActor);
  1759 /*******************************************************************************
  1760  * BlobParent
  1761  ******************************************************************************/
  1763 BlobParent::BlobParent(ContentParent* aManager, nsIDOMBlob* aBlob)
  1764   : mBlob(aBlob)
  1765   , mRemoteBlob(nullptr)
  1766   , mStrongManager(aManager)
  1767   , mOwnsBlob(true)
  1768   , mBlobIsFile(false)
  1770   MOZ_ASSERT(NS_IsMainThread());
  1771   MOZ_ASSERT(aManager);
  1772   MOZ_ASSERT(aBlob);
  1774   aBlob->AddRef();
  1776   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
  1777   mBlobIsFile = !!file;
  1780 BlobParent::BlobParent(ContentParent* aManager,
  1781                        const ParentBlobConstructorParams& aParams)
  1782   : mBlob(nullptr)
  1783   , mRemoteBlob(nullptr)
  1784   , mStrongManager(aManager)
  1785   , mOwnsBlob(false)
  1786   , mBlobIsFile(false)
  1788   MOZ_ASSERT(NS_IsMainThread());
  1789   MOZ_ASSERT(aManager);
  1791   ChildBlobConstructorParams::Type paramsType = aParams.blobParams().type();
  1793   mBlobIsFile =
  1794     paramsType == ChildBlobConstructorParams::TFileBlobConstructorParams ||
  1795     paramsType == ChildBlobConstructorParams::TMysteryBlobConstructorParams;
  1797   nsRefPtr<RemoteBlob> remoteBlob = CreateRemoteBlob(aParams);
  1798   MOZ_ASSERT(remoteBlob);
  1800   remoteBlob->SetActor(this);
  1801   remoteBlob->MaybeSetInputStream(aParams);
  1802   remoteBlob.forget(&mRemoteBlob);
  1804   mBlob = mRemoteBlob;
  1805   mOwnsBlob = true;
  1808 BlobParent::~BlobParent()
  1812 BlobParent*
  1813 BlobParent::Create(ContentParent* aManager,
  1814                    const ParentBlobConstructorParams& aParams)
  1816   MOZ_ASSERT(NS_IsMainThread());
  1817   MOZ_ASSERT(aManager);
  1819   const ChildBlobConstructorParams& blobParams = aParams.blobParams();
  1821   switch (blobParams.type()) {
  1822     case ChildBlobConstructorParams::TNormalBlobConstructorParams:
  1823     case ChildBlobConstructorParams::TFileBlobConstructorParams:
  1824     case ChildBlobConstructorParams::TMysteryBlobConstructorParams:
  1825       return new BlobParent(aManager, aParams);
  1827     case ChildBlobConstructorParams::TSlicedBlobConstructorParams: {
  1828       const SlicedBlobConstructorParams& params =
  1829         blobParams.get_SlicedBlobConstructorParams();
  1831       auto* actor =
  1832         const_cast<BlobParent*>(
  1833           static_cast<const BlobParent*>(params.sourceParent()));
  1834       MOZ_ASSERT(actor);
  1836       nsCOMPtr<nsIDOMBlob> source = actor->GetBlob();
  1837       MOZ_ASSERT(source);
  1839       nsCOMPtr<nsIDOMBlob> slice;
  1840       nsresult rv =
  1841         source->Slice(params.begin(), params.end(), params.contentType(), 3,
  1842                       getter_AddRefs(slice));
  1843       NS_ENSURE_SUCCESS(rv, nullptr);
  1845       return new BlobParent(aManager, slice);
  1848     default:
  1849       MOZ_CRASH("Unknown params!");
  1852   return nullptr;
  1855 already_AddRefed<nsIDOMBlob>
  1856 BlobParent::GetBlob()
  1858   MOZ_ASSERT(NS_IsMainThread());
  1859   MOZ_ASSERT(mBlob);
  1861   nsCOMPtr<nsIDOMBlob> blob;
  1863   // Remote blobs are held alive until the first call to GetBlob. Thereafter we
  1864   // only hold a weak reference. Normal blobs are held alive until the actor is
  1865   // destroyed.
  1866   if (mRemoteBlob && mOwnsBlob) {
  1867     blob = dont_AddRef(mBlob);
  1868     mOwnsBlob = false;
  1870   else {
  1871     blob = mBlob;
  1874   MOZ_ASSERT(blob);
  1876   return blob.forget();
  1879 bool
  1880 BlobParent::SetMysteryBlobInfo(const nsString& aName,
  1881                                const nsString& aContentType,
  1882                                uint64_t aLength,
  1883                                uint64_t aLastModifiedDate)
  1885   MOZ_ASSERT(NS_IsMainThread());
  1886   MOZ_ASSERT(mBlob);
  1887   MOZ_ASSERT(mRemoteBlob);
  1888   MOZ_ASSERT(aLastModifiedDate != UINT64_MAX);
  1890   ToConcreteBlob(mBlob)->SetLazyData(aName, aContentType, aLength,
  1891                                      aLastModifiedDate);
  1893   FileBlobConstructorParams params(aName, aContentType, aLength,
  1894                                    aLastModifiedDate);
  1895   return SendResolveMystery(params);
  1898 bool
  1899 BlobParent::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
  1901   MOZ_ASSERT(NS_IsMainThread());
  1902   MOZ_ASSERT(mBlob);
  1903   MOZ_ASSERT(mRemoteBlob);
  1905   nsString voidString;
  1906   voidString.SetIsVoid(true);
  1908   ToConcreteBlob(mBlob)->SetLazyData(voidString, aContentType, aLength,
  1909                                      UINT64_MAX);
  1911   NormalBlobConstructorParams params(aContentType, aLength);
  1912   return SendResolveMystery(params);
  1915 already_AddRefed<BlobParent::RemoteBlob>
  1916 BlobParent::CreateRemoteBlob(const ParentBlobConstructorParams& aParams)
  1918   MOZ_ASSERT(NS_IsMainThread());
  1920   const ChildBlobConstructorParams& blobParams = aParams.blobParams();
  1922   nsRefPtr<RemoteBlob> remoteBlob;
  1924   switch (blobParams.type()) {
  1925     case ChildBlobConstructorParams::TNormalBlobConstructorParams: {
  1926       const NormalBlobConstructorParams& params =
  1927         blobParams.get_NormalBlobConstructorParams();
  1928       remoteBlob = new RemoteBlob(params.contentType(), params.length());
  1929       break;
  1932     case ChildBlobConstructorParams::TFileBlobConstructorParams: {
  1933       const FileBlobConstructorParams& params =
  1934         blobParams.get_FileBlobConstructorParams();
  1935       remoteBlob =
  1936         new RemoteBlob(params.name(), params.contentType(), params.length(),
  1937                        params.modDate());
  1938       break;
  1941     case ChildBlobConstructorParams::TMysteryBlobConstructorParams: {
  1942       remoteBlob = new RemoteBlob();
  1943       break;
  1946     default:
  1947       MOZ_CRASH("Unknown params!");
  1950   MOZ_ASSERT(remoteBlob);
  1952   if (NS_FAILED(remoteBlob->SetMutable(false))) {
  1953     MOZ_CRASH("Failed to make remote blob immutable!");
  1956   return remoteBlob.forget();
  1959 void
  1960 BlobParent::NoteDyingRemoteBlob()
  1962   MOZ_ASSERT(mBlob);
  1963   MOZ_ASSERT(mRemoteBlob);
  1964   MOZ_ASSERT(!mOwnsBlob);
  1966   // This may be called on any thread due to the fact that RemoteBlob is
  1967   // designed to be passed between threads. We must start the shutdown process
  1968   // on the main thread, so we proxy here if necessary.
  1969   if (!NS_IsMainThread()) {
  1970     nsCOMPtr<nsIRunnable> runnable =
  1971       NS_NewNonOwningRunnableMethod(this, &BlobParent::NoteDyingRemoteBlob);
  1972     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
  1973       MOZ_ASSERT(false, "Should never fail!");
  1976     return;
  1979   // Must do this before calling Send__delete__ or we'll crash there trying to
  1980   // access a dangling pointer.
  1981   mBlob = nullptr;
  1982   mRemoteBlob = nullptr;
  1984   mozilla::unused << PBlobParent::Send__delete__(this);
  1987 void
  1988 BlobParent::NoteRunnableCompleted(OpenStreamRunnable* aRunnable)
  1990   MOZ_ASSERT(NS_IsMainThread());
  1992   for (uint32_t index = 0; index < mOpenStreamRunnables.Length(); index++) {
  1993     nsRevocableEventPtr<OpenStreamRunnable>& runnable =
  1994       mOpenStreamRunnables[index];
  1996     if (runnable.get() == aRunnable) {
  1997       runnable.Forget();
  1998       mOpenStreamRunnables.RemoveElementAt(index);
  1999       return;
  2003   MOZ_CRASH("Runnable not in our array!");
  2006 void
  2007 BlobParent::ActorDestroy(ActorDestroyReason aWhy)
  2009   MOZ_ASSERT(NS_IsMainThread());
  2011   if (mRemoteBlob) {
  2012     mRemoteBlob->SetActor(nullptr);
  2015   if (mBlob && mOwnsBlob) {
  2016     mBlob->Release();
  2019   mStrongManager = nullptr;
  2022 PBlobStreamParent*
  2023 BlobParent::AllocPBlobStreamParent()
  2025   MOZ_ASSERT(NS_IsMainThread());
  2027   return new InputStreamParent();
  2030 bool
  2031 BlobParent::RecvPBlobStreamConstructor(PBlobStreamParent* aActor)
  2033   MOZ_ASSERT(NS_IsMainThread());
  2034   MOZ_ASSERT(aActor);
  2035   MOZ_ASSERT(mBlob);
  2036   MOZ_ASSERT(!mRemoteBlob);
  2038   nsCOMPtr<nsIInputStream> stream;
  2039   nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
  2040   NS_ENSURE_SUCCESS(rv, false);
  2042   nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(mBlob);
  2044   nsCOMPtr<IPrivateRemoteInputStream> remoteStream;
  2045   if (remoteBlob) {
  2046     remoteStream = do_QueryInterface(stream);
  2049   // There are three cases in which we can use the stream obtained from the blob
  2050   // directly as our serialized stream:
  2051   //
  2052   //   1. The blob is not a remote blob.
  2053   //   2. The blob is a remote blob that represents this actor.
  2054   //   3. The blob is a remote blob representing a different actor but we
  2055   //      already have a non-remote, i.e. serialized, serialized stream.
  2056   //
  2057   // In all other cases we need to be on a background thread before we can get
  2058   // to the real stream.
  2059   nsCOMPtr<nsIIPCSerializableInputStream> serializableStream;
  2060   if (!remoteBlob ||
  2061       static_cast<PBlobParent*>(remoteBlob->GetPBlob()) == this ||
  2062       !remoteStream) {
  2063     serializableStream = do_QueryInterface(stream);
  2064     if (!serializableStream) {
  2065       MOZ_ASSERT(false, "Must be serializable!");
  2066       return false;
  2070   nsCOMPtr<nsIEventTarget> target =
  2071     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
  2072   NS_ENSURE_TRUE(target, false);
  2074   nsRefPtr<OpenStreamRunnable> runnable =
  2075     new OpenStreamRunnable(this, aActor, stream, serializableStream, target);
  2077   rv = runnable->Dispatch();
  2078   NS_ENSURE_SUCCESS(rv, false);
  2080   // nsRevocableEventPtr lacks some of the operators needed for anything nicer.
  2081   *mOpenStreamRunnables.AppendElement() = runnable;
  2082   return true;
  2085 bool
  2086 BlobParent::DeallocPBlobStreamParent(PBlobStreamParent* aActor)
  2088   MOZ_ASSERT(NS_IsMainThread());
  2090   delete static_cast<InputStreamParent*>(aActor);
  2091   return true;
  2094 bool
  2095 BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
  2097   MOZ_ASSERT(NS_IsMainThread());
  2098   MOZ_ASSERT(mBlob);
  2099   MOZ_ASSERT(!mRemoteBlob);
  2100   MOZ_ASSERT(mOwnsBlob);
  2102   if (!mBlobIsFile) {
  2103     MOZ_ASSERT(false, "Must always be a file!");
  2104     return false;
  2107   nsDOMFileBase* blob = ToConcreteBlob(mBlob);
  2109   switch (aParams.type()) {
  2110     case ResolveMysteryParams::TNormalBlobConstructorParams: {
  2111       const NormalBlobConstructorParams& params =
  2112         aParams.get_NormalBlobConstructorParams();
  2113       nsString voidString;
  2114       voidString.SetIsVoid(true);
  2115       blob->SetLazyData(voidString, params.contentType(),
  2116                         params.length(), UINT64_MAX);
  2117       break;
  2120     case ResolveMysteryParams::TFileBlobConstructorParams: {
  2121       const FileBlobConstructorParams& params =
  2122         aParams.get_FileBlobConstructorParams();
  2123       blob->SetLazyData(params.name(), params.contentType(),
  2124                         params.length(), params.modDate());
  2125       break;
  2128     default:
  2129       MOZ_CRASH("Unknown params!");
  2132   return true;
  2135 bool
  2136 InputStreamChild::Recv__delete__(const InputStreamParams& aParams,
  2137                                  const OptionalFileDescriptorSet& aFDs)
  2139   MOZ_ASSERT(NS_IsMainThread());
  2140   MOZ_ASSERT(mRemoteStream);
  2142   nsTArray<FileDescriptor> fds;
  2143   if (aFDs.type() == OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
  2144     FileDescriptorSetChild* fdSetActor =
  2145       static_cast<FileDescriptorSetChild*>(aFDs.get_PFileDescriptorSetChild());
  2146     MOZ_ASSERT(fdSetActor);
  2148     fdSetActor->ForgetFileDescriptors(fds);
  2149     MOZ_ASSERT(!fds.IsEmpty());
  2151     fdSetActor->Send__delete__(fdSetActor);
  2154   nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams, fds);
  2155   if (!stream) {
  2156     return false;
  2159   mRemoteStream->SetStream(stream);
  2160   return true;
  2163 bool
  2164 InputStreamParent::Recv__delete__(const InputStreamParams& aParams,
  2165                                   const OptionalFileDescriptorSet& aFDs)
  2167   MOZ_ASSERT(NS_IsMainThread());
  2168   MOZ_ASSERT(mRemoteStream);
  2170   if (aFDs.type() != OptionalFileDescriptorSet::Tvoid_t) {
  2171     NS_WARNING("Child cannot send FileDescriptors to the parent!");
  2172     return false;
  2175   nsTArray<FileDescriptor> fds;
  2176   nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams, fds);
  2177   if (!stream) {
  2178     return false;
  2181   MOZ_ASSERT(fds.IsEmpty());
  2183   mRemoteStream->SetStream(stream);
  2184   return true;

mercurial