LCOV - code coverage report
Current view: top level - ipc/glue - IPCStreamUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 16 275 5.8 %
Date: 2017-07-14 16:53:18 Functions: 4 30 13.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "IPCStreamUtils.h"
       8             : 
       9             : #include "nsIIPCSerializableInputStream.h"
      10             : 
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/dom/nsIContentChild.h"
      13             : #include "mozilla/dom/PContentParent.h"
      14             : #include "mozilla/dom/File.h"
      15             : #include "mozilla/ipc/FileDescriptorSetChild.h"
      16             : #include "mozilla/ipc/FileDescriptorSetParent.h"
      17             : #include "mozilla/ipc/InputStreamUtils.h"
      18             : #include "mozilla/ipc/IPCStreamDestination.h"
      19             : #include "mozilla/ipc/IPCStreamSource.h"
      20             : #include "mozilla/ipc/PBackgroundChild.h"
      21             : #include "mozilla/ipc/PBackgroundParent.h"
      22             : #include "mozilla/Unused.h"
      23             : #include "nsIAsyncInputStream.h"
      24             : #include "nsIAsyncOutputStream.h"
      25             : #include "nsIPipe.h"
      26             : #include "nsNetCID.h"
      27             : #include "nsStreamUtils.h"
      28             : 
      29             : using namespace mozilla::dom;
      30             : 
      31             : namespace mozilla {
      32             : namespace ipc {
      33             : 
      34             : namespace {
      35             : 
      36             : void
      37           0 : AssertValidValueToTake(const IPCStream& aVal)
      38             : {
      39           0 :   MOZ_ASSERT(aVal.type() == IPCStream::TIPCRemoteStream ||
      40             :              aVal.type() == IPCStream::TInputStreamParamsWithFds);
      41           0 : }
      42             : 
      43             : void
      44           0 : AssertValidValueToTake(const OptionalIPCStream& aVal)
      45             : {
      46           0 :   MOZ_ASSERT(aVal.type() == OptionalIPCStream::Tvoid_t ||
      47             :              aVal.type() == OptionalIPCStream::TIPCStream);
      48           0 :   if (aVal.type() == OptionalIPCStream::TIPCStream) {
      49           0 :     AssertValidValueToTake(aVal.get_IPCStream());
      50             :   }
      51           0 : }
      52             : 
      53             : // These serialization and cleanup functions could be externally exposed.  For
      54             : // now, though, keep them private to encourage use of the safer RAII
      55             : // AutoIPCStream class.
      56             : 
      57             : template<typename M>
      58             : bool
      59           0 : SerializeInputStreamWithFdsChild(nsIIPCSerializableInputStream* aStream,
      60             :                                  IPCStream& aValue,
      61             :                                  M* aManager)
      62             : {
      63           0 :   MOZ_RELEASE_ASSERT(aStream);
      64           0 :   MOZ_ASSERT(aManager);
      65             : 
      66           0 :   aValue = InputStreamParamsWithFds();
      67             :   InputStreamParamsWithFds& streamWithFds =
      68           0 :     aValue.get_InputStreamParamsWithFds();
      69             : 
      70           0 :   AutoTArray<FileDescriptor, 4> fds;
      71           0 :   aStream->Serialize(streamWithFds.stream(), fds);
      72             : 
      73           0 :   if (streamWithFds.stream().type() == InputStreamParams::T__None) {
      74           0 :     MOZ_CRASH("Serialize failed!");
      75             :   }
      76             : 
      77           0 :   if (fds.IsEmpty()) {
      78           0 :     streamWithFds.optionalFds() = void_t();
      79             :   } else {
      80             :     PFileDescriptorSetChild* fdSet =
      81           0 :       aManager->SendPFileDescriptorSetConstructor(fds[0]);
      82           0 :     for (uint32_t i = 1; i < fds.Length(); ++i) {
      83           0 :       Unused << fdSet->SendAddFileDescriptor(fds[i]);
      84             :     }
      85             : 
      86           0 :     streamWithFds.optionalFds() = fdSet;
      87             :   }
      88             : 
      89           0 :   return true;
      90             : }
      91             : 
      92             : template<typename M>
      93             : bool
      94           0 : SerializeInputStreamWithFdsParent(nsIIPCSerializableInputStream* aStream,
      95             :                                   IPCStream& aValue,
      96             :                                   M* aManager)
      97             : {
      98           0 :   MOZ_RELEASE_ASSERT(aStream);
      99           0 :   MOZ_ASSERT(aManager);
     100             : 
     101           0 :   aValue = InputStreamParamsWithFds();
     102             :   InputStreamParamsWithFds& streamWithFds =
     103           0 :     aValue.get_InputStreamParamsWithFds();
     104             : 
     105           0 :   AutoTArray<FileDescriptor, 4> fds;
     106           0 :   aStream->Serialize(streamWithFds.stream(), fds);
     107             : 
     108           0 :   if (streamWithFds.stream().type() == InputStreamParams::T__None) {
     109           0 :     MOZ_CRASH("Serialize failed!");
     110             :   }
     111             : 
     112           0 :   streamWithFds.optionalFds() = void_t();
     113           0 :   if (!fds.IsEmpty()) {
     114             :     PFileDescriptorSetParent* fdSet =
     115           0 :       aManager->SendPFileDescriptorSetConstructor(fds[0]);
     116           0 :     for (uint32_t i = 1; i < fds.Length(); ++i) {
     117           0 :       if (NS_WARN_IF(!fdSet->SendAddFileDescriptor(fds[i]))) {
     118           0 :         Unused << PFileDescriptorSetParent::Send__delete__(fdSet);
     119           0 :         fdSet = nullptr;
     120           0 :         break;
     121             :       }
     122             :     }
     123             : 
     124           0 :     if (fdSet) {
     125           0 :       streamWithFds.optionalFds() = fdSet;
     126             :     }
     127             :   }
     128             : 
     129           0 :   return true;
     130             : }
     131             : 
     132             : template<typename M>
     133             : bool
     134           0 : SerializeInputStream(nsIInputStream* aStream, IPCStream& aValue, M* aManager,
     135             :                      bool aDelayedStart)
     136             : {
     137           0 :   MOZ_ASSERT(aStream);
     138           0 :   MOZ_ASSERT(aManager);
     139             : 
     140             :   // As a fallback, attempt to stream the data across using a IPCStream
     141             :   // actor. For blocking streams, create a nonblocking pipe instead,
     142           0 :   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
     143           0 :   if (!asyncStream) {
     144           0 :     const uint32_t kBufferSize = 32768; // matches IPCStream buffer size.
     145           0 :     nsCOMPtr<nsIAsyncOutputStream> sink;
     146           0 :     nsresult rv = NS_NewPipe2(getter_AddRefs(asyncStream),
     147             :                               getter_AddRefs(sink),
     148             :                               true,
     149             :                               false,
     150             :                               kBufferSize,
     151           0 :                               UINT32_MAX);
     152           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     153           0 :       return false;
     154             :     }
     155             : 
     156             :     nsCOMPtr<nsIEventTarget> target =
     157           0 :       do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     158             : 
     159           0 :     rv = NS_AsyncCopy(aStream, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
     160             :                       kBufferSize);
     161           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     162           0 :       return false;
     163             :     }
     164             :   }
     165             : 
     166           0 :   MOZ_ASSERT(asyncStream);
     167             : 
     168           0 :   IPCRemoteStream remoteStream;
     169           0 :   remoteStream.delayedStart() = aDelayedStart;
     170           0 :   remoteStream.stream() = IPCStreamSource::Create(asyncStream, aManager);
     171           0 :   aValue = remoteStream;
     172             : 
     173           0 :   return true;
     174             : }
     175             : 
     176             : template<typename M>
     177             : bool
     178           0 : SerializeInputStreamChild(nsIInputStream* aStream, M* aManager,
     179             :                           IPCStream* aValue,
     180             :                           OptionalIPCStream* aOptionalValue,
     181             :                           bool aDelayedStart)
     182             : {
     183           0 :   MOZ_ASSERT(aStream);
     184           0 :   MOZ_ASSERT(aManager);
     185           0 :   MOZ_ASSERT(aValue || aOptionalValue);
     186             : 
     187             :   // If a stream is known to be larger than 1MB, prefer sending it in chunks.
     188           0 :   const uint64_t kTooLargeStream = 1024 * 1024;
     189             : 
     190             :   nsCOMPtr<nsIIPCSerializableInputStream> serializable =
     191           0 :     do_QueryInterface(aStream);
     192             : 
     193             :   // ExpectedSerializedLength() returns the length of the stream if serialized.
     194             :   // This is useful to decide if we want to continue using the serialization
     195             :   // directly, or if it's better to use IPCStream.
     196             :   uint64_t expectedLength =
     197           0 :     serializable ? serializable->ExpectedSerializedLength().valueOr(0) : 0;
     198           0 :   if (serializable && expectedLength < kTooLargeStream) {
     199           0 :     if (aValue) {
     200           0 :       return SerializeInputStreamWithFdsChild(serializable, *aValue, aManager);
     201             :     }
     202             : 
     203           0 :     return SerializeInputStreamWithFdsChild(serializable, *aOptionalValue,
     204           0 :                                             aManager);
     205             :   }
     206             : 
     207           0 :   if (aValue) {
     208           0 :     return SerializeInputStream(aStream, *aValue, aManager, aDelayedStart);
     209             :   }
     210             : 
     211           0 :   return SerializeInputStream(aStream, *aOptionalValue, aManager, aDelayedStart);
     212             : }
     213             : 
     214             : template<typename M>
     215             : bool
     216           0 : SerializeInputStreamParent(nsIInputStream* aStream, M* aManager,
     217             :                            IPCStream* aValue,
     218             :                            OptionalIPCStream* aOptionalValue,
     219             :                            bool aDelayedStart)
     220             : {
     221           0 :   MOZ_ASSERT(aStream);
     222           0 :   MOZ_ASSERT(aManager);
     223           0 :   MOZ_ASSERT(aValue || aOptionalValue);
     224             : 
     225             :   // If a stream is known to be larger than 1MB, prefer sending it in chunks.
     226           0 :   const uint64_t kTooLargeStream = 1024 * 1024;
     227             : 
     228             :   nsCOMPtr<nsIIPCSerializableInputStream> serializable =
     229           0 :     do_QueryInterface(aStream);
     230             :   uint64_t expectedLength =
     231           0 :     serializable ? serializable->ExpectedSerializedLength().valueOr(0) : 0;
     232             : 
     233           0 :   if (serializable && expectedLength < kTooLargeStream) {
     234           0 :     if (aValue) {
     235           0 :       return SerializeInputStreamWithFdsParent(serializable, *aValue, aManager);
     236             :     }
     237             : 
     238           0 :     return SerializeInputStreamWithFdsParent(serializable, *aOptionalValue,
     239           0 :                                              aManager);
     240             :   }
     241             : 
     242           0 :   if (aValue) {
     243           0 :     return SerializeInputStream(aStream, *aValue, aManager, aDelayedStart);
     244             :   }
     245             : 
     246           0 :   return SerializeInputStream(aStream, *aOptionalValue, aManager, aDelayedStart);
     247             : }
     248             : 
     249             : void
     250           0 : CleanupIPCStream(IPCStream& aValue, bool aConsumedByIPC, bool aDelayedStart)
     251             : {
     252           0 :   if (aValue.type() == IPCStream::T__None) {
     253           0 :     return;
     254             :   }
     255             : 
     256           0 :   if (aValue.type() == IPCStream::TInputStreamParamsWithFds) {
     257             : 
     258             :     InputStreamParamsWithFds& streamWithFds =
     259           0 :       aValue.get_InputStreamParamsWithFds();
     260             : 
     261             :     // Cleanup file descriptors if necessary
     262           0 :     if (streamWithFds.optionalFds().type() ==
     263             :         OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
     264             : 
     265           0 :       AutoTArray<FileDescriptor, 4> fds;
     266             : 
     267             :       auto fdSetActor = static_cast<FileDescriptorSetChild*>(
     268           0 :         streamWithFds.optionalFds().get_PFileDescriptorSetChild());
     269           0 :       MOZ_ASSERT(fdSetActor);
     270             : 
     271             :       // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we
     272             :       // unconditionally forget them here.  The fds themselves are auto-closed in
     273             :       // ~FileDescriptor since they originated in this process.
     274           0 :       fdSetActor->ForgetFileDescriptors(fds);
     275             : 
     276           0 :       if (!aConsumedByIPC) {
     277           0 :         Unused << fdSetActor->Send__delete__(fdSetActor);
     278             :       }
     279             : 
     280           0 :     } else if (streamWithFds.optionalFds().type() ==
     281             :                OptionalFileDescriptorSet::TPFileDescriptorSetParent) {
     282             : 
     283           0 :       AutoTArray<FileDescriptor, 4> fds;
     284             : 
     285             :       auto fdSetActor = static_cast<FileDescriptorSetParent*>(
     286           0 :         streamWithFds.optionalFds().get_PFileDescriptorSetParent());
     287           0 :       MOZ_ASSERT(fdSetActor);
     288             : 
     289             :       // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we
     290             :       // unconditionally forget them here.  The fds themselves are auto-closed in
     291             :       // ~FileDescriptor since they originated in this process.
     292           0 :       fdSetActor->ForgetFileDescriptors(fds);
     293             : 
     294           0 :       if (!aConsumedByIPC) {
     295           0 :         Unused << fdSetActor->Send__delete__(fdSetActor);
     296             :       }
     297             :     }
     298             : 
     299           0 :     return;
     300             :   }
     301             : 
     302           0 :   MOZ_ASSERT(aValue.type() == IPCStream::TIPCRemoteStream);
     303             :   IPCRemoteStreamType& remoteInputStream =
     304           0 :     aValue.get_IPCRemoteStream().stream();
     305             : 
     306           0 :   IPCStreamSource* source = nullptr;
     307           0 :   if (remoteInputStream.type() == IPCRemoteStreamType::TPChildToParentStreamChild) {
     308           0 :     source = IPCStreamSource::Cast(remoteInputStream.get_PChildToParentStreamChild());
     309             :   } else {
     310           0 :     MOZ_ASSERT(remoteInputStream.type() == IPCRemoteStreamType::TPParentToChildStreamParent);
     311           0 :     source = IPCStreamSource::Cast(remoteInputStream.get_PParentToChildStreamParent());
     312             :   }
     313             : 
     314           0 :   MOZ_ASSERT(source);
     315             : 
     316             :   // If the source stream has not been taken to be sent to the other side, we
     317             :   // can destroy it.
     318           0 :   if (!aConsumedByIPC) {
     319           0 :     source->StartDestroy();
     320           0 :     return;
     321             :   }
     322             : 
     323           0 :   if (!aDelayedStart) {
     324             :     // If we don't need to do a delayedStart, we start it now. Otherwise, the
     325             :     // Start() will be called at the first use by the
     326             :     // IPCStreamDestination::DelayedStartInputStream.
     327           0 :     source->Start();
     328             :   }
     329             : }
     330             : 
     331             : void
     332           3 : CleanupIPCStream(OptionalIPCStream& aValue, bool aConsumedByIPC, bool aDelayedStart)
     333             : {
     334           3 :   if (aValue.type() == OptionalIPCStream::Tvoid_t) {
     335           3 :     return;
     336             :   }
     337             : 
     338           0 :   CleanupIPCStream(aValue.get_IPCStream(), aConsumedByIPC, aDelayedStart);
     339             : }
     340             : 
     341             : // Returns false if the serialization should not proceed. This means that the
     342             : // inputStream is null.
     343             : bool
     344           0 : NormalizeOptionalValue(nsIInputStream* aStream,
     345             :                        IPCStream* aValue,
     346             :                        OptionalIPCStream* aOptionalValue)
     347             : {
     348           0 :   if (aValue) {
     349             :     // if aStream is null, we will crash when serializing.
     350           0 :     return true;
     351             :   }
     352             : 
     353           0 :   if (!aStream) {
     354           0 :     *aOptionalValue = void_t();
     355           0 :     return false;
     356             :   }
     357             : 
     358           0 :   *aOptionalValue = IPCStream();
     359           0 :   return true;
     360             : }
     361             : 
     362             : } // anonymous namespace
     363             : 
     364             : already_AddRefed<nsIInputStream>
     365           0 : DeserializeIPCStream(const IPCStream& aValue)
     366             : {
     367           0 :   if (aValue.type() == IPCStream::TIPCRemoteStream) {
     368           0 :     const IPCRemoteStream& remoteStream = aValue.get_IPCRemoteStream();
     369           0 :     const IPCRemoteStreamType& remoteStreamType = remoteStream.stream();
     370             :     IPCStreamDestination* destinationStream;
     371             : 
     372           0 :     if (remoteStreamType.type() == IPCRemoteStreamType::TPChildToParentStreamParent) {
     373             :       destinationStream =
     374           0 :         IPCStreamDestination::Cast(remoteStreamType.get_PChildToParentStreamParent());
     375             :     } else {
     376           0 :       MOZ_ASSERT(remoteStreamType.type() == IPCRemoteStreamType::TPParentToChildStreamChild);
     377             :       destinationStream =
     378           0 :         IPCStreamDestination::Cast(remoteStreamType.get_PParentToChildStreamChild());
     379             :     }
     380             : 
     381           0 :     destinationStream->SetDelayedStart(remoteStream.delayedStart());
     382           0 :     return destinationStream->TakeReader();
     383             :   }
     384             : 
     385             :   // Note, we explicitly do not support deserializing the PChildToParentStream actor on
     386             :   // the child side nor the PParentToChildStream actor on the parent side.
     387           0 :   MOZ_ASSERT(aValue.type() == IPCStream::TInputStreamParamsWithFds);
     388             : 
     389             :   const InputStreamParamsWithFds& streamWithFds =
     390           0 :     aValue.get_InputStreamParamsWithFds();
     391             : 
     392           0 :   AutoTArray<FileDescriptor, 4> fds;
     393           0 :   if (streamWithFds.optionalFds().type() ==
     394             :       OptionalFileDescriptorSet::TPFileDescriptorSetParent) {
     395             : 
     396             :     auto fdSetActor = static_cast<FileDescriptorSetParent*>(
     397           0 :       streamWithFds.optionalFds().get_PFileDescriptorSetParent());
     398           0 :     MOZ_ASSERT(fdSetActor);
     399             : 
     400           0 :     fdSetActor->ForgetFileDescriptors(fds);
     401           0 :     MOZ_ASSERT(!fds.IsEmpty());
     402             : 
     403           0 :     if (!fdSetActor->Send__delete__(fdSetActor)) {
     404             :       // child process is gone, warn and allow actor to clean up normally
     405           0 :       NS_WARNING("Failed to delete fd set actor.");
     406             :     }
     407           0 :   } else if (streamWithFds.optionalFds().type() ==
     408             :              OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
     409             : 
     410             :     auto fdSetActor = static_cast<FileDescriptorSetChild*>(
     411           0 :       streamWithFds.optionalFds().get_PFileDescriptorSetChild());
     412           0 :     MOZ_ASSERT(fdSetActor);
     413             : 
     414           0 :     fdSetActor->ForgetFileDescriptors(fds);
     415           0 :     MOZ_ASSERT(!fds.IsEmpty());
     416             : 
     417           0 :     Unused << fdSetActor->Send__delete__(fdSetActor);
     418             :   }
     419             : 
     420           0 :   return InputStreamHelper::DeserializeInputStream(streamWithFds.stream(), fds);
     421             : }
     422             : 
     423             : already_AddRefed<nsIInputStream>
     424           3 : DeserializeIPCStream(const OptionalIPCStream& aValue)
     425             : {
     426           3 :   if (aValue.type() == OptionalIPCStream::Tvoid_t) {
     427           3 :     return nullptr;
     428             :   }
     429             : 
     430           0 :   return DeserializeIPCStream(aValue.get_IPCStream());
     431             : }
     432             : 
     433           0 : AutoIPCStream::AutoIPCStream(bool aDelayedStart)
     434           0 :   : mInlineValue(void_t())
     435             :   , mValue(nullptr)
     436           0 :   , mOptionalValue(&mInlineValue)
     437             :   , mTaken(false)
     438           0 :   , mDelayedStart(aDelayedStart)
     439             : {
     440           0 : }
     441             : 
     442           0 : AutoIPCStream::AutoIPCStream(IPCStream& aTarget, bool aDelayedStart)
     443           0 :   : mInlineValue(void_t())
     444             :   , mValue(&aTarget)
     445             :   , mOptionalValue(nullptr)
     446             :   , mTaken(false)
     447           0 :   , mDelayedStart(aDelayedStart)
     448             : {
     449           0 : }
     450             : 
     451           3 : AutoIPCStream::AutoIPCStream(OptionalIPCStream& aTarget, bool aDelayedStart)
     452           3 :   : mInlineValue(void_t())
     453             :   , mValue(nullptr)
     454             :   , mOptionalValue(&aTarget)
     455             :   , mTaken(false)
     456           6 :   , mDelayedStart(aDelayedStart)
     457             : {
     458           3 :   *mOptionalValue = void_t();
     459           3 : }
     460             : 
     461           6 : AutoIPCStream::~AutoIPCStream()
     462             : {
     463           3 :   MOZ_ASSERT(mValue || mOptionalValue);
     464           3 :   if (mValue && IsSet()) {
     465           0 :     CleanupIPCStream(*mValue, mTaken, mDelayedStart);
     466             :   } else {
     467           3 :     CleanupIPCStream(*mOptionalValue, mTaken, mDelayedStart);
     468             :   }
     469           3 : }
     470             : 
     471             : bool
     472           0 : AutoIPCStream::Serialize(nsIInputStream* aStream, dom::nsIContentChild* aManager)
     473             : {
     474           0 :   MOZ_ASSERT(aStream || !mValue);
     475           0 :   MOZ_ASSERT(aManager);
     476           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     477           0 :   MOZ_ASSERT(!mTaken);
     478           0 :   MOZ_ASSERT(!IsSet());
     479             : 
     480             :   // If NormalizeOptionalValue returns false, we don't have to proceed.
     481           0 :   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
     482           0 :     return true;
     483             :   }
     484             : 
     485           0 :   if (!SerializeInputStreamChild(aStream, aManager, mValue, mOptionalValue,
     486           0 :                                  mDelayedStart)) {
     487           0 :     MOZ_CRASH("IPCStream creation failed!");
     488             :   }
     489             : 
     490           0 :   if (mValue) {
     491           0 :     AssertValidValueToTake(*mValue);
     492             :   } else {
     493           0 :     AssertValidValueToTake(*mOptionalValue);
     494             :   }
     495             : 
     496           0 :   return true;
     497             : }
     498             : 
     499             : bool
     500           0 : AutoIPCStream::Serialize(nsIInputStream* aStream, PBackgroundChild* aManager)
     501             : {
     502           0 :   MOZ_ASSERT(aStream || !mValue);
     503           0 :   MOZ_ASSERT(aManager);
     504           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     505           0 :   MOZ_ASSERT(!mTaken);
     506           0 :   MOZ_ASSERT(!IsSet());
     507             : 
     508             :   // If NormalizeOptionalValue returns false, we don't have to proceed.
     509           0 :   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
     510           0 :     return true;
     511             :   }
     512             : 
     513           0 :   if (!SerializeInputStreamChild(aStream, aManager, mValue, mOptionalValue,
     514           0 :                                  mDelayedStart)) {
     515           0 :     MOZ_CRASH("IPCStream creation failed!");
     516             :   }
     517             : 
     518           0 :   if (mValue) {
     519           0 :     AssertValidValueToTake(*mValue);
     520             :   } else {
     521           0 :     AssertValidValueToTake(*mOptionalValue);
     522             :   }
     523             : 
     524           0 :   return true;
     525             : }
     526             : 
     527             : bool
     528           0 : AutoIPCStream::Serialize(nsIInputStream* aStream,
     529             :                          dom::nsIContentParent* aManager)
     530             : {
     531           0 :   MOZ_ASSERT(aStream || !mValue);
     532           0 :   MOZ_ASSERT(aManager);
     533           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     534           0 :   MOZ_ASSERT(!mTaken);
     535           0 :   MOZ_ASSERT(!IsSet());
     536             : 
     537             :   // If NormalizeOptionalValue returns false, we don't have to proceed.
     538           0 :   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
     539           0 :     return true;
     540             :   }
     541             : 
     542           0 :   if (!SerializeInputStreamParent(aStream, aManager, mValue, mOptionalValue,
     543           0 :                                   mDelayedStart)) {
     544           0 :     return false;
     545             :   }
     546             : 
     547           0 :   if (mValue) {
     548           0 :     AssertValidValueToTake(*mValue);
     549             :   } else {
     550           0 :     AssertValidValueToTake(*mOptionalValue);
     551             :   }
     552             : 
     553           0 :   return true;
     554             : }
     555             : 
     556             : bool
     557           0 : AutoIPCStream::Serialize(nsIInputStream* aStream, PBackgroundParent* aManager)
     558             : {
     559           0 :   MOZ_ASSERT(aStream || !mValue);
     560           0 :   MOZ_ASSERT(aManager);
     561           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     562           0 :   MOZ_ASSERT(!mTaken);
     563           0 :   MOZ_ASSERT(!IsSet());
     564             : 
     565             :   // If NormalizeOptionalValue returns false, we don't have to proceed.
     566           0 :   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
     567           0 :     return true;
     568             :   }
     569             : 
     570           0 :   if (!SerializeInputStreamParent(aStream, aManager, mValue, mOptionalValue,
     571           0 :                                   mDelayedStart)) {
     572           0 :     return false;
     573             :   }
     574             : 
     575           0 :   if (mValue) {
     576           0 :     AssertValidValueToTake(*mValue);
     577             :   } else {
     578           0 :     AssertValidValueToTake(*mOptionalValue);
     579             :   }
     580             : 
     581           0 :   return true;
     582             : }
     583             : 
     584             : bool
     585           0 : AutoIPCStream::IsSet() const
     586             : {
     587           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     588           0 :   if (mValue) {
     589           0 :     return mValue->type() != IPCStream::T__None;
     590             :   } else {
     591           0 :     return mOptionalValue->type() != OptionalIPCStream::Tvoid_t &&
     592           0 :            mOptionalValue->get_IPCStream().type() != IPCStream::T__None;
     593             :   }
     594             : }
     595             : 
     596             : IPCStream&
     597           0 : AutoIPCStream::TakeValue()
     598             : {
     599           0 :   MOZ_ASSERT(mValue || mOptionalValue);
     600           0 :   MOZ_ASSERT(!mTaken);
     601           0 :   MOZ_ASSERT(IsSet());
     602             : 
     603           0 :   mTaken = true;
     604             : 
     605           0 :   if (mValue) {
     606           0 :     AssertValidValueToTake(*mValue);
     607           0 :     return *mValue;
     608             :   }
     609             : 
     610             :   IPCStream& value =
     611           0 :     mOptionalValue->get_IPCStream();
     612             : 
     613           0 :   AssertValidValueToTake(value);
     614           0 :   return value;
     615             : }
     616             : 
     617             : OptionalIPCStream&
     618           0 : AutoIPCStream::TakeOptionalValue()
     619             : {
     620           0 :   MOZ_ASSERT(!mTaken);
     621           0 :   MOZ_ASSERT(!mValue);
     622           0 :   MOZ_ASSERT(mOptionalValue);
     623           0 :   mTaken = true;
     624           0 :   AssertValidValueToTake(*mOptionalValue);
     625           0 :   return *mOptionalValue;
     626             : }
     627             : 
     628             : } // namespace ipc
     629             : } // namespace mozilla

Generated by: LCOV version 1.13