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 : #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
8 : #define __IPC_GLUE_IPCMESSAGEUTILS_H__
9 :
10 : #include "base/process_util.h"
11 : #include "chrome/common/ipc_message_utils.h"
12 :
13 : #include "mozilla/ArrayUtils.h"
14 : #include "mozilla/Attributes.h"
15 : #include "mozilla/DebugOnly.h"
16 : #include "mozilla/dom/ipc/StructuredCloneData.h"
17 : #include "mozilla/Maybe.h"
18 : #include "mozilla/net/WebSocketFrame.h"
19 : #include "mozilla/TimeStamp.h"
20 : #ifdef XP_WIN
21 : #include "mozilla/TimeStamp_windows.h"
22 : #endif
23 : #include "mozilla/TypeTraits.h"
24 : #include "mozilla/IntegerTypeTraits.h"
25 :
26 : #include <stdint.h>
27 :
28 : #ifdef MOZ_CRASHREPORTER
29 : #include "nsExceptionHandler.h"
30 : #endif
31 : #include "nsID.h"
32 : #include "nsIWidget.h"
33 : #include "nsMemory.h"
34 : #include "nsString.h"
35 : #include "nsTArray.h"
36 : #include "js/StructuredClone.h"
37 : #include "nsCSSPropertyID.h"
38 :
39 : #ifdef _MSC_VER
40 : #pragma warning( disable : 4800 )
41 : #endif
42 :
43 : #if !defined(OS_POSIX)
44 : // This condition must be kept in sync with the one in
45 : // ipc_message_utils.h, but this dummy definition of
46 : // base::FileDescriptor acts as a static assert that we only get one
47 : // def or the other (or neither, in which case code using
48 : // FileDescriptor fails to build)
49 : namespace base { struct FileDescriptor { }; }
50 : #endif
51 :
52 : namespace mozilla {
53 :
54 : // This is a cross-platform approximation to HANDLE, which we expect
55 : // to be typedef'd to void* or thereabouts.
56 : typedef uintptr_t WindowsHandle;
57 :
58 : // XXX there are out of place and might be generally useful. Could
59 : // move to nscore.h or something.
60 : struct void_t {
61 0 : bool operator==(const void_t&) const { return true; }
62 : };
63 : struct null_t {
64 0 : bool operator==(const null_t&) const { return true; }
65 : };
66 :
67 171 : struct SerializedStructuredCloneBuffer final
68 : {
69 : SerializedStructuredCloneBuffer&
70 0 : operator=(const SerializedStructuredCloneBuffer& aOther)
71 : {
72 0 : data.Clear();
73 0 : auto iter = aOther.data.Iter();
74 0 : while (!iter.Done()) {
75 0 : data.WriteBytes(iter.Data(), iter.RemainingInSegment());
76 0 : iter.Advance(aOther.data, iter.RemainingInSegment());
77 : }
78 0 : return *this;
79 : }
80 :
81 : bool
82 0 : operator==(const SerializedStructuredCloneBuffer& aOther) const
83 : {
84 : // The copy assignment operator and the equality operator are
85 : // needed by the IPDL generated code. We relied on the copy
86 : // assignment operator at some places but we never use the
87 : // equality operator.
88 0 : return false;
89 : }
90 :
91 : JSStructuredCloneData data;
92 : };
93 :
94 : } // namespace mozilla
95 :
96 : namespace IPC {
97 :
98 : /**
99 : * Maximum size, in bytes, of a single IPC message.
100 : */
101 : static const uint32_t MAX_MESSAGE_SIZE = 65536;
102 :
103 : /**
104 : * Generic enum serializer.
105 : *
106 : * Consider using the specializations below, such as ContiguousEnumSerializer.
107 : *
108 : * This is a generic serializer for any enum type used in IPDL.
109 : * Programmers can define ParamTraits<E> for enum type E by deriving
110 : * EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
111 : * that has to define a static IsLegalValue function returning whether
112 : * a given value is a legal value of the enum type at hand.
113 : *
114 : * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
115 : */
116 : template <typename E, typename EnumValidator>
117 : struct EnumSerializer {
118 : typedef E paramType;
119 : typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type
120 : uintParamType;
121 :
122 245 : static void Write(Message* aMsg, const paramType& aValue) {
123 245 : MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(aValue));
124 245 : WriteParam(aMsg, uintParamType(aValue));
125 245 : }
126 :
127 245 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
128 : uintParamType value;
129 245 : if (!ReadParam(aMsg, aIter, &value)) {
130 : #ifdef MOZ_CRASHREPORTER
131 0 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCReadErrorReason"),
132 : NS_LITERAL_CSTRING("Bad iter"));
133 : #endif
134 0 : return false;
135 245 : } else if (!EnumValidator::IsLegalValue(paramType(value))) {
136 : #ifdef MOZ_CRASHREPORTER
137 0 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCReadErrorReason"),
138 : NS_LITERAL_CSTRING("Illegal value"));
139 : #endif
140 0 : return false;
141 : }
142 245 : *aResult = paramType(value);
143 245 : return true;
144 : }
145 : };
146 :
147 : template <typename E,
148 : E MinLegal,
149 : E HighBound>
150 : class ContiguousEnumValidator
151 : {
152 : // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
153 : // "comparison of unsigned expression >= 0 is always true"
154 : // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
155 : template <typename T>
156 184 : static bool IsLessThanOrEqual(T a, T b) { return a <= b; }
157 :
158 : public:
159 184 : static bool IsLegalValue(E e)
160 : {
161 184 : return IsLessThanOrEqual(MinLegal, e) && e < HighBound;
162 : }
163 : };
164 :
165 : template <typename E,
166 : E MinLegal,
167 : E MaxLegal>
168 : class ContiguousEnumValidatorInclusive
169 : {
170 : // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
171 : // "comparison of unsigned expression >= 0 is always true"
172 : // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
173 : template <typename T>
174 110 : static bool IsLessThanOrEqual(T a, T b) { return a <= b; }
175 :
176 : public:
177 110 : static bool IsLegalValue(E e)
178 : {
179 110 : return IsLessThanOrEqual(MinLegal, e) && e <= MaxLegal;
180 : }
181 : };
182 :
183 : template <typename E,
184 : E AllBits>
185 : struct BitFlagsEnumValidator
186 : {
187 196 : static bool IsLegalValue(E e)
188 : {
189 196 : return (e & AllBits) == e;
190 : }
191 : };
192 :
193 : /**
194 : * Specialization of EnumSerializer for enums with contiguous enum values.
195 : *
196 : * Provide two values: MinLegal, HighBound. An enum value x will be
197 : * considered legal if MinLegal <= x < HighBound.
198 : *
199 : * For example, following is definition of serializer for enum type FOO.
200 : * \code
201 : * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
202 : *
203 : * template <>
204 : * struct ParamTraits<FOO>:
205 : * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
206 : * \endcode
207 : * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
208 : */
209 : template <typename E,
210 : E MinLegal,
211 : E HighBound>
212 : struct ContiguousEnumSerializer
213 : : EnumSerializer<E,
214 : ContiguousEnumValidator<E, MinLegal, HighBound>>
215 : {};
216 :
217 : /**
218 : * This is similar to ContiguousEnumSerializer, but the last template
219 : * parameter is expected to be the highest legal value, rather than a
220 : * sentinel value. This is intended to support enumerations that don't
221 : * have sentinel values.
222 : */
223 : template <typename E,
224 : E MinLegal,
225 : E MaxLegal>
226 : struct ContiguousEnumSerializerInclusive
227 : : EnumSerializer<E,
228 : ContiguousEnumValidatorInclusive<E, MinLegal, MaxLegal>>
229 : {};
230 :
231 : /**
232 : * Specialization of EnumSerializer for enums representing bit flags.
233 : *
234 : * Provide one value: AllBits. An enum value x will be
235 : * considered legal if (x & AllBits) == x;
236 : *
237 : * Example:
238 : * \code
239 : * enum FOO {
240 : * FOO_FIRST = 1 << 0,
241 : * FOO_SECOND = 1 << 1,
242 : * FOO_LAST = 1 << 2,
243 : * ALL_BITS = (1 << 3) - 1
244 : * };
245 : *
246 : * template <>
247 : * struct ParamTraits<FOO>:
248 : * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
249 : * \endcode
250 : */
251 : template <typename E,
252 : E AllBits>
253 : struct BitFlagsEnumSerializer
254 : : EnumSerializer<E,
255 : BitFlagsEnumValidator<E, AllBits>>
256 : {};
257 :
258 : template <>
259 : struct ParamTraits<base::ChildPrivileges>
260 : : public ContiguousEnumSerializer<base::ChildPrivileges,
261 : base::PRIVILEGES_DEFAULT,
262 : base::PRIVILEGES_LAST>
263 : { };
264 :
265 : /**
266 : * A helper class for serializing plain-old data (POD) structures.
267 : * The memory representation of the structure is written to and read from
268 : * the serialized stream directly, without individual processing of the
269 : * structure's members.
270 : *
271 : * Derive ParamTraits<T> from PlainOldDataSerializer<T> if T is POD.
272 : */
273 : template <typename T>
274 : struct PlainOldDataSerializer
275 : {
276 : // TODO: Once the mozilla::IsPod trait is in good enough shape (bug 900042),
277 : // static_assert that mozilla::IsPod<T>::value is true.
278 : typedef T paramType;
279 :
280 27 : static void Write(Message* aMsg, const paramType& aParam) {
281 27 : aMsg->WriteBytes(&aParam, sizeof(aParam));
282 27 : }
283 :
284 26 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
285 26 : return aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType));
286 : }
287 : };
288 :
289 : template<>
290 : struct ParamTraits<int8_t>
291 : {
292 : typedef int8_t paramType;
293 :
294 0 : static void Write(Message* aMsg, const paramType& aParam)
295 : {
296 0 : aMsg->WriteBytes(&aParam, sizeof(aParam));
297 0 : }
298 :
299 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
300 : {
301 0 : return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
302 : }
303 : };
304 :
305 : template<>
306 : struct ParamTraits<uint8_t>
307 : {
308 : typedef uint8_t paramType;
309 :
310 181 : static void Write(Message* aMsg, const paramType& aParam)
311 : {
312 181 : aMsg->WriteBytes(&aParam, sizeof(aParam));
313 181 : }
314 :
315 181 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
316 : {
317 181 : return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
318 : }
319 : };
320 :
321 : #if !defined(OS_POSIX)
322 : // See above re: keeping definitions in sync
323 : template<>
324 : struct ParamTraits<base::FileDescriptor>
325 : {
326 : typedef base::FileDescriptor paramType;
327 : static void Write(Message* aMsg, const paramType& aParam) {
328 : MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
329 : }
330 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
331 : MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
332 : return false;
333 : }
334 : };
335 : #endif // !defined(OS_POSIX)
336 :
337 : template <>
338 : struct ParamTraits<nsACString>
339 : {
340 : typedef nsACString paramType;
341 :
342 9525 : static void Write(Message* aMsg, const paramType& aParam)
343 : {
344 9525 : bool isVoid = aParam.IsVoid();
345 9525 : aMsg->WriteBool(isVoid);
346 :
347 9525 : if (isVoid)
348 : // represents a nullptr pointer
349 0 : return;
350 :
351 9525 : uint32_t length = aParam.Length();
352 9525 : WriteParam(aMsg, length);
353 9525 : aMsg->WriteBytes(aParam.BeginReading(), length);
354 : }
355 :
356 9466 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
357 : {
358 : bool isVoid;
359 9466 : if (!aMsg->ReadBool(aIter, &isVoid))
360 0 : return false;
361 :
362 9466 : if (isVoid) {
363 0 : aResult->SetIsVoid(true);
364 0 : return true;
365 : }
366 :
367 : uint32_t length;
368 9466 : if (!ReadParam(aMsg, aIter, &length)) {
369 0 : return false;
370 : }
371 9465 : aResult->SetLength(length);
372 :
373 9466 : return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(), length);
374 : }
375 :
376 : static void Log(const paramType& aParam, std::wstring* aLog)
377 : {
378 : if (aParam.IsVoid())
379 : aLog->append(L"(NULL)");
380 : else
381 : aLog->append(UTF8ToWide(aParam.BeginReading()));
382 : }
383 : };
384 :
385 : template <>
386 : struct ParamTraits<nsAString>
387 : {
388 : typedef nsAString paramType;
389 :
390 143 : static void Write(Message* aMsg, const paramType& aParam)
391 : {
392 143 : bool isVoid = aParam.IsVoid();
393 143 : aMsg->WriteBool(isVoid);
394 :
395 143 : if (isVoid)
396 : // represents a nullptr pointer
397 0 : return;
398 :
399 143 : uint32_t length = aParam.Length();
400 143 : WriteParam(aMsg, length);
401 143 : aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t));
402 : }
403 :
404 141 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
405 : {
406 : bool isVoid;
407 141 : if (!aMsg->ReadBool(aIter, &isVoid))
408 0 : return false;
409 :
410 141 : if (isVoid) {
411 0 : aResult->SetIsVoid(true);
412 0 : return true;
413 : }
414 :
415 : uint32_t length;
416 141 : if (!ReadParam(aMsg, aIter, &length)) {
417 0 : return false;
418 : }
419 141 : aResult->SetLength(length);
420 :
421 141 : return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(), length * sizeof(char16_t));
422 : }
423 :
424 : static void Log(const paramType& aParam, std::wstring* aLog)
425 : {
426 : if (aParam.IsVoid())
427 : aLog->append(L"(NULL)");
428 : else {
429 : #ifdef WCHAR_T_IS_UTF16
430 : aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading()));
431 : #else
432 : uint32_t length = aParam.Length();
433 : for (uint32_t index = 0; index < length; index++) {
434 : aLog->push_back(std::wstring::value_type(aParam[index]));
435 : }
436 : #endif
437 : }
438 : }
439 : };
440 :
441 : template <>
442 : struct ParamTraits<nsCString> : ParamTraits<nsACString>
443 : {
444 : typedef nsCString paramType;
445 : };
446 :
447 : template <>
448 : struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString>
449 : {
450 : typedef nsLiteralCString paramType;
451 : };
452 :
453 : #ifdef MOZILLA_INTERNAL_API
454 :
455 : template<>
456 : struct ParamTraits<nsAutoCString> : ParamTraits<nsCString>
457 : {
458 : typedef nsAutoCString paramType;
459 : };
460 :
461 : #endif // MOZILLA_INTERNAL_API
462 :
463 : template <>
464 : struct ParamTraits<nsString> : ParamTraits<nsAString>
465 : {
466 : typedef nsString paramType;
467 : };
468 :
469 : template <>
470 : struct ParamTraits<nsLiteralString> : ParamTraits<nsAString>
471 : {
472 : typedef nsLiteralString paramType;
473 : };
474 :
475 : template <>
476 : struct ParamTraits<nsDependentSubstring> : ParamTraits<nsAString>
477 : {
478 : typedef nsDependentSubstring paramType;
479 : };
480 :
481 : template <>
482 : struct ParamTraits<nsDependentCSubstring> : ParamTraits<nsACString>
483 : {
484 : typedef nsDependentCSubstring paramType;
485 : };
486 :
487 : #ifdef MOZILLA_INTERNAL_API
488 :
489 : template<>
490 : struct ParamTraits<nsAutoString> : ParamTraits<nsString>
491 : {
492 : typedef nsAutoString paramType;
493 : };
494 :
495 : #endif // MOZILLA_INTERNAL_API
496 :
497 : // Pickle::ReadBytes and ::WriteBytes take the length in ints, so we must
498 : // ensure there is no overflow. This returns |false| if it would overflow.
499 : // Otherwise, it returns |true| and places the byte length in |aByteLength|.
500 : bool ByteLengthIsValid(uint32_t aNumElements, size_t aElementSize, int* aByteLength);
501 :
502 : // Note: IPDL will sometimes codegen specialized implementations of
503 : // nsTArray serialization and deserialization code in
504 : // implementSpecialArrayPickling(). This is needed when ParamTraits<E>
505 : // is not defined.
506 : template <typename E>
507 : struct ParamTraits<nsTArray<E>>
508 : {
509 : typedef nsTArray<E> paramType;
510 :
511 : // We write arrays of integer or floating-point data using a single pickling
512 : // call, rather than writing each element individually. We deliberately do
513 : // not use mozilla::IsPod here because it is perfectly reasonable to have
514 : // a data structure T for which IsPod<T>::value is true, yet also have a
515 : // ParamTraits<T> specialization.
516 : static const bool sUseWriteBytes = (mozilla::IsIntegral<E>::value ||
517 : mozilla::IsFloatingPoint<E>::value);
518 :
519 370 : static void Write(Message* aMsg, const paramType& aParam)
520 : {
521 370 : uint32_t length = aParam.Length();
522 370 : WriteParam(aMsg, length);
523 :
524 : if (sUseWriteBytes) {
525 50 : int pickledLength = 0;
526 50 : MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
527 50 : aMsg->WriteBytes(aParam.Elements(), pickledLength);
528 : } else {
529 320 : const E* elems = aParam.Elements();
530 1584 : for (uint32_t index = 0; index < length; index++) {
531 1264 : WriteParam(aMsg, elems[index]);
532 : }
533 : }
534 370 : }
535 :
536 : // This method uses infallible allocation so that an OOM failure will
537 : // show up as an OOM crash rather than an IPC FatalError.
538 368 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
539 : {
540 : uint32_t length;
541 368 : if (!ReadParam(aMsg, aIter, &length)) {
542 0 : return false;
543 : }
544 :
545 : if (sUseWriteBytes) {
546 50 : int pickledLength = 0;
547 50 : if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
548 0 : return false;
549 : }
550 :
551 50 : E* elements = aResult->AppendElements(length);
552 50 : return aMsg->ReadBytesInto(aIter, elements, pickledLength);
553 : } else {
554 318 : aResult->SetCapacity(length);
555 :
556 1385 : for (uint32_t index = 0; index < length; index++) {
557 1067 : E* element = aResult->AppendElement();
558 1067 : if (!ReadParam(aMsg, aIter, element)) {
559 0 : return false;
560 : }
561 : }
562 318 : return true;
563 : }
564 : }
565 :
566 : static void Log(const paramType& aParam, std::wstring* aLog)
567 : {
568 : for (uint32_t index = 0; index < aParam.Length(); index++) {
569 : if (index) {
570 : aLog->append(L" ");
571 : }
572 : LogParam(aParam[index], aLog);
573 : }
574 : }
575 : };
576 :
577 : template<typename E>
578 : struct ParamTraits<FallibleTArray<E>>
579 : {
580 : typedef FallibleTArray<E> paramType;
581 :
582 0 : static void Write(Message* aMsg, const paramType& aParam)
583 : {
584 0 : WriteParam(aMsg, static_cast<const nsTArray<E>&>(aParam));
585 0 : }
586 :
587 : // Deserialize the array infallibly, but return a FallibleTArray.
588 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
589 : {
590 0 : nsTArray<E> temp;
591 0 : if (!ReadParam(aMsg, aIter, &temp))
592 0 : return false;
593 :
594 0 : aResult->SwapElements(temp);
595 0 : return true;
596 : }
597 :
598 : static void Log(const paramType& aParam, std::wstring* aLog)
599 : {
600 : LogParam(static_cast<const nsTArray<E>&>(aParam), aLog);
601 : }
602 : };
603 :
604 : template<typename E, size_t N>
605 : struct ParamTraits<AutoTArray<E, N>> : ParamTraits<nsTArray<E>>
606 : {
607 : typedef AutoTArray<E, N> paramType;
608 : };
609 :
610 : template<>
611 : struct ParamTraits<float>
612 : {
613 : typedef float paramType;
614 :
615 1410 : static void Write(Message* aMsg, const paramType& aParam)
616 : {
617 1410 : aMsg->WriteBytes(&aParam, sizeof(paramType));
618 1410 : }
619 :
620 1404 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
621 : {
622 1404 : return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
623 : }
624 :
625 : static void Log(const paramType& aParam, std::wstring* aLog)
626 : {
627 : aLog->append(StringPrintf(L"%g", aParam));
628 : }
629 : };
630 :
631 : template <>
632 : struct ParamTraits<nsCSSPropertyID>
633 : : public ContiguousEnumSerializer<nsCSSPropertyID,
634 : eCSSProperty_UNKNOWN,
635 : eCSSProperty_COUNT>
636 : {};
637 :
638 : template<>
639 : struct ParamTraits<mozilla::void_t>
640 : {
641 : typedef mozilla::void_t paramType;
642 31 : static void Write(Message* aMsg, const paramType& aParam) { }
643 : static bool
644 31 : Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
645 : {
646 31 : *aResult = paramType();
647 31 : return true;
648 : }
649 : };
650 :
651 : template<>
652 : struct ParamTraits<mozilla::null_t>
653 : {
654 : typedef mozilla::null_t paramType;
655 5903 : static void Write(Message* aMsg, const paramType& aParam) { }
656 : static bool
657 5903 : Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
658 : {
659 5903 : *aResult = paramType();
660 5903 : return true;
661 : }
662 : };
663 :
664 : template<>
665 : struct ParamTraits<nsID>
666 : {
667 : typedef nsID paramType;
668 :
669 0 : static void Write(Message* aMsg, const paramType& aParam)
670 : {
671 0 : WriteParam(aMsg, aParam.m0);
672 0 : WriteParam(aMsg, aParam.m1);
673 0 : WriteParam(aMsg, aParam.m2);
674 0 : for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) {
675 0 : WriteParam(aMsg, aParam.m3[i]);
676 : }
677 0 : }
678 :
679 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
680 : {
681 0 : if(!ReadParam(aMsg, aIter, &(aResult->m0)) ||
682 0 : !ReadParam(aMsg, aIter, &(aResult->m1)) ||
683 0 : !ReadParam(aMsg, aIter, &(aResult->m2)))
684 0 : return false;
685 :
686 0 : for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++)
687 0 : if (!ReadParam(aMsg, aIter, &(aResult->m3[i])))
688 0 : return false;
689 :
690 0 : return true;
691 : }
692 :
693 : static void Log(const paramType& aParam, std::wstring* aLog)
694 : {
695 : aLog->append(L"{");
696 : aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-",
697 : aParam.m0,
698 : aParam.m1,
699 : aParam.m2));
700 : for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++)
701 : aLog->append(StringPrintf(L"%2.2X", aParam.m3[i]));
702 : aLog->append(L"}");
703 : }
704 : };
705 :
706 : template<>
707 : struct ParamTraits<mozilla::TimeDuration>
708 : {
709 : typedef mozilla::TimeDuration paramType;
710 0 : static void Write(Message* aMsg, const paramType& aParam)
711 : {
712 0 : WriteParam(aMsg, aParam.mValue);
713 0 : }
714 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
715 : {
716 0 : return ReadParam(aMsg, aIter, &aResult->mValue);
717 : };
718 : };
719 :
720 : template<>
721 : struct ParamTraits<mozilla::TimeStamp>
722 : {
723 : typedef mozilla::TimeStamp paramType;
724 354 : static void Write(Message* aMsg, const paramType& aParam)
725 : {
726 354 : WriteParam(aMsg, aParam.mValue);
727 354 : }
728 302 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
729 : {
730 302 : return ReadParam(aMsg, aIter, &aResult->mValue);
731 : };
732 : };
733 :
734 : #ifdef XP_WIN
735 :
736 : template<>
737 : struct ParamTraits<mozilla::TimeStampValue>
738 : {
739 : typedef mozilla::TimeStampValue paramType;
740 : static void Write(Message* aMsg, const paramType& aParam)
741 : {
742 : WriteParam(aMsg, aParam.mGTC);
743 : WriteParam(aMsg, aParam.mQPC);
744 : WriteParam(aMsg, aParam.mHasQPC);
745 : WriteParam(aMsg, aParam.mIsNull);
746 : }
747 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
748 : {
749 : return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
750 : ReadParam(aMsg, aIter, &aResult->mQPC) &&
751 : ReadParam(aMsg, aIter, &aResult->mHasQPC) &&
752 : ReadParam(aMsg, aIter, &aResult->mIsNull));
753 : }
754 : };
755 :
756 : #endif
757 :
758 : template <>
759 : struct ParamTraits<mozilla::dom::ipc::StructuredCloneData>
760 : {
761 : typedef mozilla::dom::ipc::StructuredCloneData paramType;
762 :
763 2 : static void Write(Message* aMsg, const paramType& aParam)
764 : {
765 2 : aParam.WriteIPCParams(aMsg);
766 2 : }
767 :
768 2 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
769 : {
770 2 : return aResult->ReadIPCParams(aMsg, aIter);
771 : }
772 :
773 : static void Log(const paramType& aParam, std::wstring* aLog)
774 : {
775 : LogParam(aParam.DataLength(), aLog);
776 : }
777 : };
778 :
779 : template <>
780 : struct ParamTraits<mozilla::net::WebSocketFrameData>
781 : {
782 : typedef mozilla::net::WebSocketFrameData paramType;
783 :
784 0 : static void Write(Message* aMsg, const paramType& aParam)
785 : {
786 0 : aParam.WriteIPCParams(aMsg);
787 0 : }
788 :
789 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
790 : {
791 0 : return aResult->ReadIPCParams(aMsg, aIter);
792 : }
793 : };
794 :
795 : template <>
796 : struct ParamTraits<JSStructuredCloneData>
797 : {
798 : typedef JSStructuredCloneData paramType;
799 :
800 46 : static void Write(Message* aMsg, const paramType& aParam)
801 : {
802 46 : MOZ_ASSERT(!(aParam.Size() % sizeof(uint64_t)));
803 46 : WriteParam(aMsg, aParam.Size());
804 46 : auto iter = aParam.Iter();
805 128 : while (!iter.Done()) {
806 41 : aMsg->WriteBytes(iter.Data(), iter.RemainingInSegment(), sizeof(uint64_t));
807 41 : iter.Advance(aParam, iter.RemainingInSegment());
808 : }
809 46 : }
810 :
811 44 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
812 : {
813 44 : size_t length = 0;
814 44 : if (!ReadParam(aMsg, aIter, &length)) {
815 0 : return false;
816 : }
817 44 : MOZ_ASSERT(!(length % sizeof(uint64_t)));
818 :
819 88 : mozilla::BufferList<InfallibleAllocPolicy> buffers(0, 0, 4096);
820 :
821 : // Borrowing is not suitable to use for IPC to hand out data
822 : // because we often want to store the data somewhere for
823 : // processing after IPC has released the underlying buffers. One
824 : // case is PContentChild::SendGetXPCOMProcessAttributes. We can't
825 : // return a borrowed buffer because the out param outlives the
826 : // IPDL callback.
827 44 : if (length && !aMsg->ExtractBuffers(aIter, length, &buffers, sizeof(uint64_t))) {
828 0 : return false;
829 : }
830 :
831 : bool success;
832 : mozilla::BufferList<js::SystemAllocPolicy> out =
833 88 : buffers.MoveFallible<js::SystemAllocPolicy>(&success);
834 44 : if (!success) {
835 0 : return false;
836 : }
837 :
838 44 : *aResult = JSStructuredCloneData(Move(out));
839 :
840 44 : return true;
841 : }
842 : };
843 :
844 : template <>
845 : struct ParamTraits<mozilla::SerializedStructuredCloneBuffer>
846 : {
847 : typedef mozilla::SerializedStructuredCloneBuffer paramType;
848 :
849 44 : static void Write(Message* aMsg, const paramType& aParam)
850 : {
851 44 : WriteParam(aMsg, aParam.data);
852 44 : }
853 :
854 42 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
855 : {
856 42 : return ReadParam(aMsg, aIter, &aResult->data);
857 : }
858 :
859 : static void Log(const paramType& aParam, std::wstring* aLog)
860 : {
861 : LogParam(aParam.data.Size(), aLog);
862 : }
863 : };
864 :
865 : template <>
866 : struct ParamTraits<nsIWidget::TouchPointerState>
867 : : public BitFlagsEnumSerializer<nsIWidget::TouchPointerState,
868 : nsIWidget::TouchPointerState::ALL_BITS>
869 : {
870 : };
871 :
872 : template<class T>
873 : struct ParamTraits<mozilla::Maybe<T>>
874 : {
875 : typedef mozilla::Maybe<T> paramType;
876 :
877 94 : static void Write(Message* msg, const paramType& param)
878 : {
879 94 : if (param.isSome()) {
880 13 : WriteParam(msg, true);
881 13 : WriteParam(msg, param.value());
882 : } else {
883 81 : WriteParam(msg, false);
884 : }
885 94 : }
886 :
887 94 : static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
888 : {
889 : bool isSome;
890 94 : if (!ReadParam(msg, iter, &isSome)) {
891 0 : return false;
892 : }
893 94 : if (isSome) {
894 8 : T tmp;
895 13 : if (!ReadParam(msg, iter, &tmp)) {
896 0 : return false;
897 : }
898 13 : *result = mozilla::Some(mozilla::Move(tmp));
899 : } else {
900 81 : *result = mozilla::Nothing();
901 : }
902 94 : return true;
903 : }
904 : };
905 :
906 : } /* namespace IPC */
907 :
908 : #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
|