1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: sw=4 ts=4 et :
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 DOM_PLUGINS_PLUGINMESSAGEUTILS_H
8 #define DOM_PLUGINS_PLUGINMESSAGEUTILS_H
9 
10 #include "ipc/IPCMessageUtils.h"
11 #include "base/message_loop.h"
12 
13 #include "mozilla/ipc/CrossProcessMutex.h"
14 #include "mozilla/ipc/MessageChannel.h"
15 #include "mozilla/ipc/ProtocolUtils.h"
16 #include "mozilla/UniquePtr.h"
17 #include "gfxipc/ShadowLayerUtils.h"
18 
19 #include "npapi.h"
20 #include "npruntime.h"
21 #include "npfunctions.h"
22 #include "nsString.h"
23 #include "nsTArray.h"
24 #include "mozilla/Logging.h"
25 #include "nsHashKeys.h"
26 #ifdef MOZ_CRASHREPORTER
27 #  include "nsExceptionHandler.h"
28 #endif
29 #ifdef XP_MACOSX
30 #include "PluginInterposeOSX.h"
31 #else
32 namespace mac_plugin_interposing { class NSCursorInfo { }; }
33 #endif
34 using mac_plugin_interposing::NSCursorInfo;
35 
36 namespace mozilla {
37 namespace plugins {
38 
39 using layers::SurfaceDescriptorX11;
40 
41 enum ScriptableObjectType
42 {
43   LocalObject,
44   Proxy
45 };
46 
47 mozilla::ipc::RacyInterruptPolicy
48 MediateRace(const mozilla::ipc::MessageChannel::MessageInfo& parent,
49             const mozilla::ipc::MessageChannel::MessageInfo& child);
50 
51 std::string
52 MungePluginDsoPath(const std::string& path);
53 std::string
54 UnmungePluginDsoPath(const std::string& munged);
55 
56 extern mozilla::LogModule* GetPluginLog();
57 
58 #if defined(_MSC_VER)
59 #define FULLFUNCTION __FUNCSIG__
60 #elif defined(__GNUC__)
61 #define FULLFUNCTION __PRETTY_FUNCTION__
62 #else
63 #define FULLFUNCTION __FUNCTION__
64 #endif
65 
66 #define PLUGIN_LOG_DEBUG(args) MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, args)
67 #define PLUGIN_LOG_DEBUG_FUNCTION MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, ("%s", FULLFUNCTION))
68 #define PLUGIN_LOG_DEBUG_METHOD MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, ("%s [%p]", FULLFUNCTION, (void*) this))
69 
70 /**
71  * This is NPByteRange without the linked list.
72  */
73 struct IPCByteRange
74 {
75   int32_t offset;
76   uint32_t length;
77 };
78 
79 typedef nsTArray<IPCByteRange> IPCByteRanges;
80 
81 typedef nsCString Buffer;
82 
83 struct NPRemoteWindow
84 {
85   NPRemoteWindow();
86   uint64_t window;
87   int32_t x;
88   int32_t y;
89   uint32_t width;
90   uint32_t height;
91   NPRect clipRect;
92   NPWindowType type;
93 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
94   VisualID visualID;
95   Colormap colormap;
96 #endif /* XP_UNIX */
97 #if defined(XP_MACOSX) || defined(XP_WIN)
98   double contentsScaleFactor;
99 #endif
100 };
101 
102 // This struct is like NPAudioDeviceChangeDetails, only it uses a
103 // std::wstring instead of a const wchar_t* for the defaultDevice.
104 // This gives us the necessary memory-ownership semantics without
105 // requiring C++ objects in npapi.h.
106 struct NPAudioDeviceChangeDetailsIPC
107 {
108   int32_t flow;
109   int32_t role;
110   std::wstring defaultDevice;
111 };
112 
113 #ifdef XP_WIN
114 typedef HWND NativeWindowHandle;
115 #elif defined(MOZ_X11)
116 typedef XID NativeWindowHandle;
117 #elif defined(XP_DARWIN) || defined(ANDROID)
118 typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
119 #else
120 #error Need NativeWindowHandle for this platform
121 #endif
122 
123 #ifdef XP_WIN
124 typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
125 typedef HANDLE DXGISharedSurfaceHandle;
126 #else
127 typedef mozilla::null_t WindowsSharedMemoryHandle;
128 typedef mozilla::null_t DXGISharedSurfaceHandle;
129 #endif
130 
131 // XXX maybe not the best place for these. better one?
132 
133 #define VARSTR(v_)  case v_: return #v_
134 inline const char*
NPPVariableToString(NPPVariable aVar)135 NPPVariableToString(NPPVariable aVar)
136 {
137     switch (aVar) {
138         VARSTR(NPPVpluginNameString);
139         VARSTR(NPPVpluginDescriptionString);
140         VARSTR(NPPVpluginWindowBool);
141         VARSTR(NPPVpluginTransparentBool);
142         VARSTR(NPPVjavaClass);
143         VARSTR(NPPVpluginWindowSize);
144         VARSTR(NPPVpluginTimerInterval);
145 
146         VARSTR(NPPVpluginScriptableInstance);
147         VARSTR(NPPVpluginScriptableIID);
148 
149         VARSTR(NPPVjavascriptPushCallerBool);
150 
151         VARSTR(NPPVpluginKeepLibraryInMemory);
152         VARSTR(NPPVpluginNeedsXEmbed);
153 
154         VARSTR(NPPVpluginScriptableNPObject);
155 
156         VARSTR(NPPVformValue);
157 
158         VARSTR(NPPVpluginUrlRequestsDisplayedBool);
159 
160         VARSTR(NPPVpluginWantsAllNetworkStreams);
161 
162 #ifdef XP_MACOSX
163         VARSTR(NPPVpluginDrawingModel);
164         VARSTR(NPPVpluginEventModel);
165 #endif
166 
167 #ifdef XP_WIN
168         VARSTR(NPPVpluginRequiresAudioDeviceChanges);
169 #endif
170 
171     default: return "???";
172     }
173 }
174 
175 inline const char*
NPNVariableToString(NPNVariable aVar)176 NPNVariableToString(NPNVariable aVar)
177 {
178     switch(aVar) {
179         VARSTR(NPNVxDisplay);
180         VARSTR(NPNVxtAppContext);
181         VARSTR(NPNVnetscapeWindow);
182         VARSTR(NPNVjavascriptEnabledBool);
183         VARSTR(NPNVasdEnabledBool);
184         VARSTR(NPNVisOfflineBool);
185 
186         VARSTR(NPNVserviceManager);
187         VARSTR(NPNVDOMElement);
188         VARSTR(NPNVDOMWindow);
189         VARSTR(NPNVToolkit);
190         VARSTR(NPNVSupportsXEmbedBool);
191 
192         VARSTR(NPNVWindowNPObject);
193 
194         VARSTR(NPNVPluginElementNPObject);
195 
196         VARSTR(NPNVSupportsWindowless);
197 
198         VARSTR(NPNVprivateModeBool);
199         VARSTR(NPNVdocumentOrigin);
200 
201 #ifdef XP_WIN
202         VARSTR(NPNVaudioDeviceChangeDetails);
203 #endif
204 
205     default: return "???";
206     }
207 }
208 #undef VARSTR
209 
IsPluginThread()210 inline bool IsPluginThread()
211 {
212   MessageLoop* loop = MessageLoop::current();
213   if (!loop)
214       return false;
215   return (loop->type() == MessageLoop::TYPE_UI);
216 }
217 
AssertPluginThread()218 inline void AssertPluginThread()
219 {
220   MOZ_RELEASE_ASSERT(IsPluginThread(), "Should be on the plugin's main thread!");
221 }
222 
223 #define ENSURE_PLUGIN_THREAD(retval) \
224   PR_BEGIN_MACRO \
225     if (!IsPluginThread()) { \
226       NS_WARNING("Not running on the plugin's main thread!"); \
227       return (retval); \
228     } \
229   PR_END_MACRO
230 
231 #define ENSURE_PLUGIN_THREAD_VOID() \
232   PR_BEGIN_MACRO \
233     if (!IsPluginThread()) { \
234       NS_WARNING("Not running on the plugin's main thread!"); \
235       return; \
236     } \
237   PR_END_MACRO
238 
239 void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o);
240 void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v);
241 
IsDrawingModelDirect(int16_t aModel)242 inline bool IsDrawingModelDirect(int16_t aModel)
243 {
244     return aModel == NPDrawingModelAsyncBitmapSurface
245 #if defined(XP_WIN)
246            || aModel == NPDrawingModelAsyncWindowsDXGISurface
247 #endif
248            ;
249 }
250 
251 // in NPAPI, char* == nullptr is sometimes meaningful.  the following is
252 // helper code for dealing with nullable nsCString's
253 inline nsCString
NullableString(const char * aString)254 NullableString(const char* aString)
255 {
256     if (!aString) {
257         return NullCString();
258     }
259     return nsCString(aString);
260 }
261 
262 inline const char*
NullableStringGet(const nsCString & str)263 NullableStringGet(const nsCString& str)
264 {
265   if (str.IsVoid())
266     return nullptr;
267 
268   return str.get();
269 }
270 
271 struct DeletingObjectEntry : public nsPtrHashKey<NPObject>
272 {
DeletingObjectEntryDeletingObjectEntry273   explicit DeletingObjectEntry(const NPObject* key)
274     : nsPtrHashKey<NPObject>(key)
275     , mDeleted(false)
276   { }
277 
278   bool mDeleted;
279 };
280 
281 } /* namespace plugins */
282 
283 } /* namespace mozilla */
284 
285 namespace IPC {
286 
287 template <>
288 struct ParamTraits<NPRect>
289 {
290   typedef NPRect paramType;
291 
292   static void Write(Message* aMsg, const paramType& aParam)
293   {
294     WriteParam(aMsg, aParam.top);
295     WriteParam(aMsg, aParam.left);
296     WriteParam(aMsg, aParam.bottom);
297     WriteParam(aMsg, aParam.right);
298   }
299 
300   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
301   {
302     uint16_t top, left, bottom, right;
303     if (ReadParam(aMsg, aIter, &top) &&
304         ReadParam(aMsg, aIter, &left) &&
305         ReadParam(aMsg, aIter, &bottom) &&
306         ReadParam(aMsg, aIter, &right)) {
307       aResult->top = top;
308       aResult->left = left;
309       aResult->bottom = bottom;
310       aResult->right = right;
311       return true;
312     }
313     return false;
314   }
315 
316   static void Log(const paramType& aParam, std::wstring* aLog)
317   {
318     aLog->append(StringPrintf(L"[%u, %u, %u, %u]", aParam.top, aParam.left,
319                               aParam.bottom, aParam.right));
320   }
321 };
322 
323 template <>
324 struct ParamTraits<NPWindowType>
325 {
326   typedef NPWindowType paramType;
327 
328   static void Write(Message* aMsg, const paramType& aParam)
329   {
330     aMsg->WriteInt16(int16_t(aParam));
331   }
332 
333   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
334   {
335     int16_t result;
336     if (aMsg->ReadInt16(aIter, &result)) {
337       *aResult = paramType(result);
338       return true;
339     }
340     return false;
341   }
342 
343   static void Log(const paramType& aParam, std::wstring* aLog)
344   {
345     aLog->append(StringPrintf(L"%d", int16_t(aParam)));
346   }
347 };
348 
349 template <>
350 struct ParamTraits<mozilla::plugins::NPRemoteWindow>
351 {
352   typedef mozilla::plugins::NPRemoteWindow paramType;
353 
354   static void Write(Message* aMsg, const paramType& aParam)
355   {
356     aMsg->WriteUInt64(aParam.window);
357     WriteParam(aMsg, aParam.x);
358     WriteParam(aMsg, aParam.y);
359     WriteParam(aMsg, aParam.width);
360     WriteParam(aMsg, aParam.height);
361     WriteParam(aMsg, aParam.clipRect);
362     WriteParam(aMsg, aParam.type);
363 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
364     aMsg->WriteULong(aParam.visualID);
365     aMsg->WriteULong(aParam.colormap);
366 #endif
367 #if defined(XP_MACOSX) || defined(XP_WIN)
368     aMsg->WriteDouble(aParam.contentsScaleFactor);
369 #endif
370   }
371 
372   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
373   {
374     uint64_t window;
375     int32_t x, y;
376     uint32_t width, height;
377     NPRect clipRect;
378     NPWindowType type;
379     if (!(aMsg->ReadUInt64(aIter, &window) &&
380           ReadParam(aMsg, aIter, &x) &&
381           ReadParam(aMsg, aIter, &y) &&
382           ReadParam(aMsg, aIter, &width) &&
383           ReadParam(aMsg, aIter, &height) &&
384           ReadParam(aMsg, aIter, &clipRect) &&
385           ReadParam(aMsg, aIter, &type)))
386       return false;
387 
388 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
389     unsigned long visualID;
390     unsigned long colormap;
391     if (!(aMsg->ReadULong(aIter, &visualID) &&
392           aMsg->ReadULong(aIter, &colormap)))
393       return false;
394 #endif
395 
396 #if defined(XP_MACOSX) || defined(XP_WIN)
397     double contentsScaleFactor;
398     if (!aMsg->ReadDouble(aIter, &contentsScaleFactor))
399       return false;
400 #endif
401 
402     aResult->window = window;
403     aResult->x = x;
404     aResult->y = y;
405     aResult->width = width;
406     aResult->height = height;
407     aResult->clipRect = clipRect;
408     aResult->type = type;
409 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
410     aResult->visualID = visualID;
411     aResult->colormap = colormap;
412 #endif
413 #if defined(XP_MACOSX) || defined(XP_WIN)
414     aResult->contentsScaleFactor = contentsScaleFactor;
415 #endif
416     return true;
417   }
418 
419   static void Log(const paramType& aParam, std::wstring* aLog)
420   {
421     aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d",
422                               (unsigned long)aParam.window,
423                               aParam.x, aParam.y, aParam.width,
424                               aParam.height, (long)aParam.type));
425   }
426 };
427 
428 #ifdef XP_MACOSX
429 template <>
430 struct ParamTraits<NPNSString*>
431 {
432   typedef NPNSString* paramType;
433 
434   // Empty string writes a length of 0 and no buffer.
435   // We don't write a nullptr terminating character in buffers.
436   static void Write(Message* aMsg, const paramType& aParam)
437   {
438     CFStringRef cfString = (CFStringRef)aParam;
439 
440     // Write true if we have a string, false represents nullptr.
441     aMsg->WriteBool(!!cfString);
442     if (!cfString) {
443       return;
444     }
445 
446     long length = ::CFStringGetLength(cfString);
447     WriteParam(aMsg, length);
448     if (length == 0) {
449       return;
450     }
451 
452     // Attempt to get characters without any allocation/conversion.
453     if (::CFStringGetCharactersPtr(cfString)) {
454       aMsg->WriteBytes(::CFStringGetCharactersPtr(cfString), length * sizeof(UniChar));
455     } else {
456       UniChar *buffer = (UniChar*)moz_xmalloc(length * sizeof(UniChar));
457       ::CFStringGetCharacters(cfString, ::CFRangeMake(0, length), buffer);
458       aMsg->WriteBytes(buffer, length * sizeof(UniChar));
459       free(buffer);
460     }
461   }
462 
463   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
464   {
465     bool haveString = false;
466     if (!aMsg->ReadBool(aIter, &haveString)) {
467       return false;
468     }
469     if (!haveString) {
470       *aResult = nullptr;
471       return true;
472     }
473 
474     long length;
475     if (!ReadParam(aMsg, aIter, &length)) {
476       return false;
477     }
478 
479     // Avoid integer multiplication overflow.
480     if (length > INT_MAX / static_cast<long>(sizeof(UniChar))) {
481       return false;
482     }
483 
484     auto chars = mozilla::MakeUnique<UniChar[]>(length);
485     if (length != 0) {
486       if (!aMsg->ReadBytesInto(aIter, chars.get(), length * sizeof(UniChar))) {
487         return false;
488       }
489     }
490 
491     *aResult = (NPNSString*)::CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)chars.get(),
492                                                       length * sizeof(UniChar),
493                                                       kCFStringEncodingUTF16, false);
494     if (!*aResult) {
495       return false;
496     }
497 
498     return true;
499   }
500 };
501 #endif
502 
503 #ifdef XP_MACOSX
504 template <>
505 struct ParamTraits<NSCursorInfo>
506 {
507   typedef NSCursorInfo paramType;
508 
509   static void Write(Message* aMsg, const paramType& aParam)
510   {
511     NSCursorInfo::Type type = aParam.GetType();
512 
513     aMsg->WriteInt(type);
514 
515     nsPoint hotSpot = aParam.GetHotSpot();
516     WriteParam(aMsg, hotSpot.x);
517     WriteParam(aMsg, hotSpot.y);
518 
519     uint32_t dataLength = aParam.GetCustomImageDataLength();
520     WriteParam(aMsg, dataLength);
521     if (dataLength == 0) {
522       return;
523     }
524 
525     uint8_t* buffer = (uint8_t*)moz_xmalloc(dataLength);
526     memcpy(buffer, aParam.GetCustomImageData(), dataLength);
527     aMsg->WriteBytes(buffer, dataLength);
528     free(buffer);
529   }
530 
531   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
532   {
533     NSCursorInfo::Type type;
534     if (!aMsg->ReadInt(aIter, (int*)&type)) {
535       return false;
536     }
537 
538     nscoord hotSpotX, hotSpotY;
539     if (!ReadParam(aMsg, aIter, &hotSpotX) ||
540         !ReadParam(aMsg, aIter, &hotSpotY)) {
541       return false;
542     }
543 
544     uint32_t dataLength;
545     if (!ReadParam(aMsg, aIter, &dataLength)) {
546       return false;
547     }
548 
549     auto data = mozilla::MakeUnique<uint8_t[]>(dataLength);
550     if (dataLength != 0) {
551       if (!aMsg->ReadBytesInto(aIter, data.get(), dataLength)) {
552         return false;
553       }
554     }
555 
556     aResult->SetType(type);
557     aResult->SetHotSpot(nsPoint(hotSpotX, hotSpotY));
558     aResult->SetCustomImageData(data.get(), dataLength);
559 
560     return true;
561   }
562 
563   static void Log(const paramType& aParam, std::wstring* aLog)
564   {
565     const char* typeName = aParam.GetTypeName();
566     nsPoint hotSpot = aParam.GetHotSpot();
567     int hotSpotX, hotSpotY;
568 #ifdef NS_COORD_IS_FLOAT
569     hotSpotX = rint(hotSpot.x);
570     hotSpotY = rint(hotSpot.y);
571 #else
572     hotSpotX = hotSpot.x;
573     hotSpotY = hotSpot.y;
574 #endif
575     uint32_t dataLength = aParam.GetCustomImageDataLength();
576     uint8_t* data = aParam.GetCustomImageData();
577 
578     aLog->append(StringPrintf(L"[%s, (%i %i), %u, %p]",
579                               typeName, hotSpotX, hotSpotY, dataLength, data));
580   }
581 };
582 #else
583 template<>
584 struct ParamTraits<NSCursorInfo>
585 {
586   typedef NSCursorInfo paramType;
587   static void Write(Message* aMsg, const paramType& aParam) {
588     NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
589   }
590   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
591     NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
592     return false;
593   }
594 };
595 #endif // #ifdef XP_MACOSX
596 
597 template <>
598 struct ParamTraits<mozilla::plugins::IPCByteRange>
599 {
600   typedef mozilla::plugins::IPCByteRange paramType;
601 
602   static void Write(Message* aMsg, const paramType& aParam)
603   {
604     WriteParam(aMsg, aParam.offset);
605     WriteParam(aMsg, aParam.length);
606   }
607 
608   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
609   {
610     paramType p;
611     if (ReadParam(aMsg, aIter, &p.offset) &&
612         ReadParam(aMsg, aIter, &p.length)) {
613       *aResult = p;
614       return true;
615     }
616     return false;
617   }
618 };
619 
620 template <>
621 struct ParamTraits<NPNVariable>
622 {
623   typedef NPNVariable paramType;
624 
625   static void Write(Message* aMsg, const paramType& aParam)
626   {
627     WriteParam(aMsg, int(aParam));
628   }
629 
630   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
631   {
632     int intval;
633     if (ReadParam(aMsg, aIter, &intval)) {
634       *aResult = paramType(intval);
635       return true;
636     }
637     return false;
638   }
639 };
640 
641 template<>
642 struct ParamTraits<NPNURLVariable>
643 {
644   typedef NPNURLVariable paramType;
645 
646   static void Write(Message* aMsg, const paramType& aParam)
647   {
648     WriteParam(aMsg, int(aParam));
649   }
650 
651   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
652   {
653     int intval;
654     if (ReadParam(aMsg, aIter, &intval)) {
655       switch (intval) {
656       case NPNURLVCookie:
657       case NPNURLVProxy:
658         *aResult = paramType(intval);
659         return true;
660       }
661     }
662     return false;
663   }
664 };
665 
666 
667 template<>
668 struct ParamTraits<NPCoordinateSpace>
669 {
670   typedef NPCoordinateSpace paramType;
671 
672   static void Write(Message* aMsg, const paramType& aParam)
673   {
674     WriteParam(aMsg, int32_t(aParam));
675   }
676 
677   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
678   {
679     int32_t intval;
680     if (ReadParam(aMsg, aIter, &intval)) {
681       switch (intval) {
682       case NPCoordinateSpacePlugin:
683       case NPCoordinateSpaceWindow:
684       case NPCoordinateSpaceFlippedWindow:
685       case NPCoordinateSpaceScreen:
686       case NPCoordinateSpaceFlippedScreen:
687         *aResult = paramType(intval);
688         return true;
689       }
690     }
691     return false;
692   }
693 };
694 
695 template <>
696 struct ParamTraits<mozilla::plugins::NPAudioDeviceChangeDetailsIPC>
697 {
698   typedef mozilla::plugins::NPAudioDeviceChangeDetailsIPC paramType;
699 
700   static void Write(Message* aMsg, const paramType& aParam)
701   {
702     WriteParam(aMsg, aParam.flow);
703     WriteParam(aMsg, aParam.role);
704     WriteParam(aMsg, aParam.defaultDevice);
705   }
706 
707   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
708   {
709     int32_t flow, role;
710     std::wstring defaultDevice;
711     if (ReadParam(aMsg, aIter, &flow) &&
712         ReadParam(aMsg, aIter, &role) &&
713         ReadParam(aMsg, aIter, &defaultDevice)) {
714       aResult->flow = flow;
715       aResult->role = role;
716       aResult->defaultDevice = defaultDevice;
717       return true;
718     }
719     return false;
720   }
721 
722   static void Log(const paramType& aParam, std::wstring* aLog)
723   {
724     aLog->append(StringPrintf(L"[%d, %d, %S]", aParam.flow, aParam.role,
725                               aParam.defaultDevice.c_str()));
726   }
727 };
728 
729 } /* namespace IPC */
730 
731 
732 // Serializing NPEvents is completely platform-specific and can be rather
733 // intricate depending on the platform.  So for readability we split it
734 // into separate files and have the only macro crud live here.
735 //
736 // NB: these guards are based on those where struct NPEvent is defined
737 // in npapi.h.  They should be kept in sync.
738 #if defined(XP_MACOSX)
739 #  include "mozilla/plugins/NPEventOSX.h"
740 #elif defined(XP_WIN)
741 #  include "mozilla/plugins/NPEventWindows.h"
742 #elif defined(ANDROID)
743 #  include "mozilla/plugins/NPEventAndroid.h"
744 #elif defined(XP_UNIX)
745 #  include "mozilla/plugins/NPEventUnix.h"
746 #else
747 #  error Unsupported platform
748 #endif
749 
750 #endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */
751