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