ipc/glue/IPCMessageUtils.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:5cf2306512c5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et 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/TimeStamp.h"
15 #ifdef XP_WIN
16 #include "mozilla/TimeStamp_windows.h"
17 #endif
18 #include "mozilla/TypedEnum.h"
19 #include "mozilla/IntegerTypeTraits.h"
20
21 #include <stdint.h>
22
23 #include "nsID.h"
24 #include "nsMemory.h"
25 #include "nsString.h"
26 #include "nsTArray.h"
27 #include "js/StructuredClone.h"
28 #include "nsCSSProperty.h"
29
30 #ifdef _MSC_VER
31 #pragma warning( disable : 4800 )
32 #endif
33
34 #if !defined(OS_POSIX)
35 // This condition must be kept in sync with the one in
36 // ipc_message_utils.h, but this dummy definition of
37 // base::FileDescriptor acts as a static assert that we only get one
38 // def or the other (or neither, in which case code using
39 // FileDescriptor fails to build)
40 namespace base { struct FileDescriptor { }; }
41 #endif
42
43 namespace mozilla {
44
45 // This is a cross-platform approximation to HANDLE, which we expect
46 // to be typedef'd to void* or thereabouts.
47 typedef uintptr_t WindowsHandle;
48
49 // XXX there are out of place and might be generally useful. Could
50 // move to nscore.h or something.
51 struct void_t {
52 bool operator==(const void_t&) const { return true; }
53 };
54 struct null_t {
55 bool operator==(const null_t&) const { return true; }
56 };
57
58 struct SerializedStructuredCloneBuffer
59 {
60 SerializedStructuredCloneBuffer()
61 : data(nullptr), dataLength(0)
62 { }
63
64 SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther)
65 {
66 *this = aOther;
67 }
68
69 bool
70 operator==(const SerializedStructuredCloneBuffer& aOther) const
71 {
72 return this->data == aOther.data &&
73 this->dataLength == aOther.dataLength;
74 }
75
76 SerializedStructuredCloneBuffer&
77 operator=(const JSAutoStructuredCloneBuffer& aOther)
78 {
79 data = aOther.data();
80 dataLength = aOther.nbytes();
81 return *this;
82 }
83
84 uint64_t* data;
85 size_t dataLength;
86 };
87
88 } // namespace mozilla
89
90 namespace IPC {
91
92 /**
93 * Generic enum serializer.
94 *
95 * Consider using the specializations below, such as ContiguousEnumSerializer.
96 *
97 * This is a generic serializer for any enum type used in IPDL.
98 * Programmers can define ParamTraits<E> for enum type E by deriving
99 * EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
100 * that has to define a static IsLegalValue function returning whether
101 * a given value is a legal value of the enum type at hand.
102 *
103 * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
104 */
105 template <typename E, typename EnumValidator>
106 struct EnumSerializer {
107 typedef E paramType;
108 typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type
109 uintParamType;
110
111 static void Write(Message* aMsg, const paramType& aValue) {
112 MOZ_ASSERT(EnumValidator::IsLegalValue(aValue));
113 WriteParam(aMsg, uintParamType(aValue));
114 }
115
116 static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
117 uintParamType value;
118 if(!ReadParam(aMsg, aIter, &value) ||
119 !EnumValidator::IsLegalValue(paramType(value))) {
120 return false;
121 }
122 *aResult = paramType(value);
123 return true;
124 }
125 };
126
127 template <typename E,
128 E MinLegal,
129 E HighBound>
130 struct ContiguousEnumValidator
131 {
132 static bool IsLegalValue(E e)
133 {
134 return MinLegal <= e && e < HighBound;
135 }
136 };
137
138 template <typename E,
139 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal,
140 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound>
141 class ContiguousTypedEnumValidator
142 {
143 // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
144 // "comparison of unsigned expression >= 0 is always true"
145 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
146 template <typename T>
147 static bool IsLessThanOrEqual(T a, T b) { return a <= b; }
148
149 public:
150 static bool IsLegalValue(E e)
151 {
152 typedef MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) ActualEnumType;
153 return IsLessThanOrEqual(MinLegal, ActualEnumType(e)) &&
154 ActualEnumType(e) < HighBound;
155 }
156 };
157
158 template <typename E,
159 E AllBits>
160 struct BitFlagsEnumValidator
161 {
162 static bool IsLegalValue(E e)
163 {
164 return (e & AllBits) == e;
165 }
166 };
167
168 template <typename E,
169 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits>
170 struct BitFlagsTypedEnumValidator
171 {
172 static bool IsLegalValue(E e)
173 {
174 return (e & AllBits) == e;
175 }
176 };
177
178 /**
179 * Specialization of EnumSerializer for enums with contiguous enum values.
180 *
181 * Provide two values: MinLegal, HighBound. An enum value x will be
182 * considered legal if MinLegal <= x < HighBound.
183 *
184 * For example, following is definition of serializer for enum type FOO.
185 * \code
186 * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
187 *
188 * template <>
189 * struct ParamTraits<FOO>:
190 * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
191 * \endcode
192 * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
193 */
194 template <typename E,
195 E MinLegal,
196 E HighBound>
197 struct ContiguousEnumSerializer
198 : EnumSerializer<E,
199 ContiguousEnumValidator<E, MinLegal, HighBound>>
200 {};
201
202 /**
203 * Similar to ContiguousEnumSerializer, but for MFBT typed enums
204 * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when
205 * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly.
206 */
207 template <typename E,
208 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal,
209 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound>
210 struct ContiguousTypedEnumSerializer
211 : EnumSerializer<E,
212 ContiguousTypedEnumValidator<E, MinLegal, HighBound>>
213 {};
214
215 /**
216 * Specialization of EnumSerializer for enums representing bit flags.
217 *
218 * Provide one value: AllBits. An enum value x will be
219 * considered legal if (x & AllBits) == x;
220 *
221 * Example:
222 * \code
223 * enum FOO {
224 * FOO_FIRST = 1 << 0,
225 * FOO_SECOND = 1 << 1,
226 * FOO_LAST = 1 << 2,
227 * ALL_BITS = (1 << 3) - 1
228 * };
229 *
230 * template <>
231 * struct ParamTraits<FOO>:
232 * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
233 * \endcode
234 */
235 template <typename E,
236 E AllBits>
237 struct BitFlagsEnumSerializer
238 : EnumSerializer<E,
239 BitFlagsEnumValidator<E, AllBits>>
240 {};
241
242 /**
243 * Similar to BitFlagsEnumSerializer, but for MFBT typed enums
244 * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when
245 * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly.
246 */
247 template <typename E,
248 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits>
249 struct BitFlagsTypedEnumSerializer
250 : EnumSerializer<E,
251 BitFlagsTypedEnumValidator<E, AllBits>>
252 {};
253
254 template <>
255 struct ParamTraits<base::ChildPrivileges>
256 : public ContiguousEnumSerializer<base::ChildPrivileges,
257 base::PRIVILEGES_DEFAULT,
258 base::PRIVILEGES_LAST>
259 { };
260
261 template<>
262 struct ParamTraits<int8_t>
263 {
264 typedef int8_t paramType;
265
266 static void Write(Message* aMsg, const paramType& aParam)
267 {
268 aMsg->WriteBytes(&aParam, sizeof(aParam));
269 }
270
271 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
272 {
273 const char* outp;
274 if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult)))
275 return false;
276
277 *aResult = *reinterpret_cast<const paramType*>(outp);
278 return true;
279 }
280 };
281
282 template<>
283 struct ParamTraits<uint8_t>
284 {
285 typedef uint8_t paramType;
286
287 static void Write(Message* aMsg, const paramType& aParam)
288 {
289 aMsg->WriteBytes(&aParam, sizeof(aParam));
290 }
291
292 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
293 {
294 const char* outp;
295 if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult)))
296 return false;
297
298 *aResult = *reinterpret_cast<const paramType*>(outp);
299 return true;
300 }
301 };
302
303 #if !defined(OS_POSIX)
304 // See above re: keeping definitions in sync
305 template<>
306 struct ParamTraits<base::FileDescriptor>
307 {
308 typedef base::FileDescriptor paramType;
309 static void Write(Message* aMsg, const paramType& aParam) {
310 NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform");
311 }
312 static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
313 NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform");
314 return false;
315 }
316 };
317 #endif // !defined(OS_POSIX)
318
319 template <>
320 struct ParamTraits<nsACString>
321 {
322 typedef nsACString paramType;
323
324 static void Write(Message* aMsg, const paramType& aParam)
325 {
326 bool isVoid = aParam.IsVoid();
327 aMsg->WriteBool(isVoid);
328
329 if (isVoid)
330 // represents a nullptr pointer
331 return;
332
333 uint32_t length = aParam.Length();
334 WriteParam(aMsg, length);
335 aMsg->WriteBytes(aParam.BeginReading(), length);
336 }
337
338 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
339 {
340 bool isVoid;
341 if (!aMsg->ReadBool(aIter, &isVoid))
342 return false;
343
344 if (isVoid) {
345 aResult->SetIsVoid(true);
346 return true;
347 }
348
349 uint32_t length;
350 if (ReadParam(aMsg, aIter, &length)) {
351 const char* buf;
352 if (aMsg->ReadBytes(aIter, &buf, length)) {
353 aResult->Assign(buf, length);
354 return true;
355 }
356 }
357 return false;
358 }
359
360 static void Log(const paramType& aParam, std::wstring* aLog)
361 {
362 if (aParam.IsVoid())
363 aLog->append(L"(NULL)");
364 else
365 aLog->append(UTF8ToWide(aParam.BeginReading()));
366 }
367 };
368
369 template <>
370 struct ParamTraits<nsAString>
371 {
372 typedef nsAString paramType;
373
374 static void Write(Message* aMsg, const paramType& aParam)
375 {
376 bool isVoid = aParam.IsVoid();
377 aMsg->WriteBool(isVoid);
378
379 if (isVoid)
380 // represents a nullptr pointer
381 return;
382
383 uint32_t length = aParam.Length();
384 WriteParam(aMsg, length);
385 aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t));
386 }
387
388 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
389 {
390 bool isVoid;
391 if (!aMsg->ReadBool(aIter, &isVoid))
392 return false;
393
394 if (isVoid) {
395 aResult->SetIsVoid(true);
396 return true;
397 }
398
399 uint32_t length;
400 if (ReadParam(aMsg, aIter, &length)) {
401 const char16_t* buf;
402 if (aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(&buf),
403 length * sizeof(char16_t))) {
404 aResult->Assign(buf, length);
405 return true;
406 }
407 }
408 return false;
409 }
410
411 static void Log(const paramType& aParam, std::wstring* aLog)
412 {
413 if (aParam.IsVoid())
414 aLog->append(L"(NULL)");
415 else {
416 #ifdef WCHAR_T_IS_UTF16
417 aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading()));
418 #else
419 uint32_t length = aParam.Length();
420 for (uint32_t index = 0; index < length; index++) {
421 aLog->push_back(std::wstring::value_type(aParam[index]));
422 }
423 #endif
424 }
425 }
426 };
427
428 template <>
429 struct ParamTraits<nsCString> : ParamTraits<nsACString>
430 {
431 typedef nsCString paramType;
432 };
433
434 template <>
435 struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString>
436 {
437 typedef nsLiteralCString paramType;
438 };
439
440 #ifdef MOZILLA_INTERNAL_API
441
442 template<>
443 struct ParamTraits<nsAutoCString> : ParamTraits<nsCString>
444 {
445 typedef nsAutoCString paramType;
446 };
447
448 #endif // MOZILLA_INTERNAL_API
449
450 template <>
451 struct ParamTraits<nsString> : ParamTraits<nsAString>
452 {
453 typedef nsString paramType;
454 };
455
456 template <>
457 struct ParamTraits<nsLiteralString> : ParamTraits<nsAString>
458 {
459 typedef nsLiteralString paramType;
460 };
461
462 template <typename E>
463 struct ParamTraits<FallibleTArray<E> >
464 {
465 typedef FallibleTArray<E> paramType;
466
467 static void Write(Message* aMsg, const paramType& aParam)
468 {
469 uint32_t length = aParam.Length();
470 WriteParam(aMsg, length);
471 for (uint32_t index = 0; index < length; index++) {
472 WriteParam(aMsg, aParam[index]);
473 }
474 }
475
476 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
477 {
478 uint32_t length;
479 if (!ReadParam(aMsg, aIter, &length)) {
480 return false;
481 }
482
483 aResult->SetCapacity(length);
484 for (uint32_t index = 0; index < length; index++) {
485 E* element = aResult->AppendElement();
486 if (!(element && ReadParam(aMsg, aIter, element))) {
487 return false;
488 }
489 }
490
491 return true;
492 }
493
494 static void Log(const paramType& aParam, std::wstring* aLog)
495 {
496 for (uint32_t index = 0; index < aParam.Length(); index++) {
497 if (index) {
498 aLog->append(L" ");
499 }
500 LogParam(aParam[index], aLog);
501 }
502 }
503 };
504
505 template<typename E>
506 struct ParamTraits<InfallibleTArray<E> >
507 {
508 typedef InfallibleTArray<E> paramType;
509
510 static void Write(Message* aMsg, const paramType& aParam)
511 {
512 WriteParam(aMsg, static_cast<const FallibleTArray<E>&>(aParam));
513 }
514
515 // deserialize the array fallibly, but return an InfallibleTArray
516 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
517 {
518 FallibleTArray<E> temp;
519 if (!ReadParam(aMsg, aIter, &temp))
520 return false;
521
522 aResult->SwapElements(temp);
523 return true;
524 }
525
526 static void Log(const paramType& aParam, std::wstring* aLog)
527 {
528 LogParam(static_cast<const FallibleTArray<E>&>(aParam), aLog);
529 }
530 };
531
532 template<>
533 struct ParamTraits<float>
534 {
535 typedef float paramType;
536
537 static void Write(Message* aMsg, const paramType& aParam)
538 {
539 aMsg->WriteBytes(&aParam, sizeof(paramType));
540 }
541
542 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
543 {
544 const char* outFloat;
545 if (!aMsg->ReadBytes(aIter, &outFloat, sizeof(float)))
546 return false;
547 *aResult = *reinterpret_cast<const float*>(outFloat);
548 return true;
549 }
550
551 static void Log(const paramType& aParam, std::wstring* aLog)
552 {
553 aLog->append(StringPrintf(L"%g", aParam));
554 }
555 };
556
557 template <>
558 struct ParamTraits<nsCSSProperty>
559 : public ContiguousEnumSerializer<nsCSSProperty,
560 eCSSProperty_UNKNOWN,
561 eCSSProperty_COUNT>
562 {};
563
564 template<>
565 struct ParamTraits<mozilla::void_t>
566 {
567 typedef mozilla::void_t paramType;
568 static void Write(Message* aMsg, const paramType& aParam) { }
569 static bool
570 Read(const Message* aMsg, void** aIter, paramType* aResult)
571 {
572 *aResult = paramType();
573 return true;
574 }
575 };
576
577 template<>
578 struct ParamTraits<mozilla::null_t>
579 {
580 typedef mozilla::null_t paramType;
581 static void Write(Message* aMsg, const paramType& aParam) { }
582 static bool
583 Read(const Message* aMsg, void** aIter, paramType* aResult)
584 {
585 *aResult = paramType();
586 return true;
587 }
588 };
589
590 template<>
591 struct ParamTraits<nsID>
592 {
593 typedef nsID paramType;
594
595 static void Write(Message* aMsg, const paramType& aParam)
596 {
597 WriteParam(aMsg, aParam.m0);
598 WriteParam(aMsg, aParam.m1);
599 WriteParam(aMsg, aParam.m2);
600 for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) {
601 WriteParam(aMsg, aParam.m3[i]);
602 }
603 }
604
605 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
606 {
607 if(!ReadParam(aMsg, aIter, &(aResult->m0)) ||
608 !ReadParam(aMsg, aIter, &(aResult->m1)) ||
609 !ReadParam(aMsg, aIter, &(aResult->m2)))
610 return false;
611
612 for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++)
613 if (!ReadParam(aMsg, aIter, &(aResult->m3[i])))
614 return false;
615
616 return true;
617 }
618
619 static void Log(const paramType& aParam, std::wstring* aLog)
620 {
621 aLog->append(L"{");
622 aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-",
623 aParam.m0,
624 aParam.m1,
625 aParam.m2));
626 for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++)
627 aLog->append(StringPrintf(L"%2.2X", aParam.m3[i]));
628 aLog->append(L"}");
629 }
630 };
631
632 template<>
633 struct ParamTraits<mozilla::TimeDuration>
634 {
635 typedef mozilla::TimeDuration paramType;
636 static void Write(Message* aMsg, const paramType& aParam)
637 {
638 WriteParam(aMsg, aParam.mValue);
639 }
640 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
641 {
642 return ReadParam(aMsg, aIter, &aResult->mValue);
643 };
644 };
645
646 template<>
647 struct ParamTraits<mozilla::TimeStamp>
648 {
649 typedef mozilla::TimeStamp paramType;
650 static void Write(Message* aMsg, const paramType& aParam)
651 {
652 WriteParam(aMsg, aParam.mValue);
653 }
654 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
655 {
656 return ReadParam(aMsg, aIter, &aResult->mValue);
657 };
658 };
659
660 #ifdef XP_WIN
661
662 template<>
663 struct ParamTraits<mozilla::TimeStampValue>
664 {
665 typedef mozilla::TimeStampValue paramType;
666 static void Write(Message* aMsg, const paramType& aParam)
667 {
668 WriteParam(aMsg, aParam.mGTC);
669 WriteParam(aMsg, aParam.mQPC);
670 WriteParam(aMsg, aParam.mHasQPC);
671 WriteParam(aMsg, aParam.mIsNull);
672 }
673 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
674 {
675 return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
676 ReadParam(aMsg, aIter, &aResult->mQPC) &&
677 ReadParam(aMsg, aIter, &aResult->mHasQPC) &&
678 ReadParam(aMsg, aIter, &aResult->mIsNull));
679 }
680 };
681
682 #endif
683
684 template <>
685 struct ParamTraits<mozilla::SerializedStructuredCloneBuffer>
686 {
687 typedef mozilla::SerializedStructuredCloneBuffer paramType;
688
689 static void Write(Message* aMsg, const paramType& aParam)
690 {
691 WriteParam(aMsg, aParam.dataLength);
692 if (aParam.dataLength) {
693 // Structured clone data must be 64-bit aligned.
694 aMsg->WriteBytes(aParam.data, aParam.dataLength, sizeof(uint64_t));
695 }
696 }
697
698 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
699 {
700 if (!ReadParam(aMsg, aIter, &aResult->dataLength)) {
701 return false;
702 }
703
704 if (aResult->dataLength) {
705 const char** buffer =
706 const_cast<const char**>(reinterpret_cast<char**>(&aResult->data));
707 // Structured clone data must be 64-bit aligned.
708 if (!aMsg->ReadBytes(aIter, buffer, aResult->dataLength,
709 sizeof(uint64_t))) {
710 return false;
711 }
712 } else {
713 aResult->data = nullptr;
714 }
715
716 return true;
717 }
718
719 static void Log(const paramType& aParam, std::wstring* aLog)
720 {
721 LogParam(aParam.dataLength, aLog);
722 }
723 };
724
725 } /* namespace IPC */
726
727 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */

mercurial