|
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__ */ |