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
|