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