summaryrefslogtreecommitdiffstats
path: root/dom/plugins/ipc/PluginMessageUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/plugins/ipc/PluginMessageUtils.h')
-rw-r--r--dom/plugins/ipc/PluginMessageUtils.h750
1 files changed, 750 insertions, 0 deletions
diff --git a/dom/plugins/ipc/PluginMessageUtils.h b/dom/plugins/ipc/PluginMessageUtils.h
new file mode 100644
index 000000000..55be59d62
--- /dev/null
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -0,0 +1,750 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=4 ts=4 et :
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DOM_PLUGINS_PLUGINMESSAGEUTILS_H
+#define DOM_PLUGINS_PLUGINMESSAGEUTILS_H
+
+#include "ipc/IPCMessageUtils.h"
+#include "base/message_loop.h"
+
+#include "mozilla/ipc/CrossProcessMutex.h"
+#include "mozilla/ipc/MessageChannel.h"
+#include "mozilla/ipc/ProtocolUtils.h"
+#include "mozilla/UniquePtr.h"
+#include "gfxipc/ShadowLayerUtils.h"
+
+#include "npapi.h"
+#include "npruntime.h"
+#include "npfunctions.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "mozilla/Logging.h"
+#include "nsHashKeys.h"
+#ifdef MOZ_CRASHREPORTER
+# include "nsExceptionHandler.h"
+#endif
+#ifdef XP_MACOSX
+#include "PluginInterposeOSX.h"
+#else
+namespace mac_plugin_interposing { class NSCursorInfo { }; }
+#endif
+using mac_plugin_interposing::NSCursorInfo;
+
+namespace mozilla {
+namespace plugins {
+
+using layers::SurfaceDescriptorX11;
+
+enum ScriptableObjectType
+{
+ LocalObject,
+ Proxy
+};
+
+mozilla::ipc::RacyInterruptPolicy
+MediateRace(const mozilla::ipc::MessageChannel::MessageInfo& parent,
+ const mozilla::ipc::MessageChannel::MessageInfo& child);
+
+std::string
+MungePluginDsoPath(const std::string& path);
+std::string
+UnmungePluginDsoPath(const std::string& munged);
+
+extern mozilla::LogModule* GetPluginLog();
+
+#if defined(_MSC_VER)
+#define FULLFUNCTION __FUNCSIG__
+#elif defined(__GNUC__)
+#define FULLFUNCTION __PRETTY_FUNCTION__
+#else
+#define FULLFUNCTION __FUNCTION__
+#endif
+
+#define PLUGIN_LOG_DEBUG(args) MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, args)
+#define PLUGIN_LOG_DEBUG_FUNCTION MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, ("%s", FULLFUNCTION))
+#define PLUGIN_LOG_DEBUG_METHOD MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, ("%s [%p]", FULLFUNCTION, (void*) this))
+
+/**
+ * This is NPByteRange without the linked list.
+ */
+struct IPCByteRange
+{
+ int32_t offset;
+ uint32_t length;
+};
+
+typedef nsTArray<IPCByteRange> IPCByteRanges;
+
+typedef nsCString Buffer;
+
+struct NPRemoteWindow
+{
+ NPRemoteWindow();
+ uint64_t window;
+ int32_t x;
+ int32_t y;
+ uint32_t width;
+ uint32_t height;
+ NPRect clipRect;
+ NPWindowType type;
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+ VisualID visualID;
+ Colormap colormap;
+#endif /* XP_UNIX */
+#if defined(XP_MACOSX) || defined(XP_WIN)
+ double contentsScaleFactor;
+#endif
+};
+
+// This struct is like NPAudioDeviceChangeDetails, only it uses a
+// std::wstring instead of a const wchar_t* for the defaultDevice.
+// This gives us the necessary memory-ownership semantics without
+// requiring C++ objects in npapi.h.
+struct NPAudioDeviceChangeDetailsIPC
+{
+ int32_t flow;
+ int32_t role;
+ std::wstring defaultDevice;
+};
+
+#ifdef XP_WIN
+typedef HWND NativeWindowHandle;
+#elif defined(MOZ_X11)
+typedef XID NativeWindowHandle;
+#elif defined(XP_DARWIN) || defined(ANDROID)
+typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
+#else
+#error Need NativeWindowHandle for this platform
+#endif
+
+#ifdef XP_WIN
+typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
+typedef HANDLE DXGISharedSurfaceHandle;
+#else
+typedef mozilla::null_t WindowsSharedMemoryHandle;
+typedef mozilla::null_t DXGISharedSurfaceHandle;
+#endif
+
+// XXX maybe not the best place for these. better one?
+
+#define VARSTR(v_) case v_: return #v_
+inline const char*
+NPPVariableToString(NPPVariable aVar)
+{
+ switch (aVar) {
+ VARSTR(NPPVpluginNameString);
+ VARSTR(NPPVpluginDescriptionString);
+ VARSTR(NPPVpluginWindowBool);
+ VARSTR(NPPVpluginTransparentBool);
+ VARSTR(NPPVjavaClass);
+ VARSTR(NPPVpluginWindowSize);
+ VARSTR(NPPVpluginTimerInterval);
+
+ VARSTR(NPPVpluginScriptableInstance);
+ VARSTR(NPPVpluginScriptableIID);
+
+ VARSTR(NPPVjavascriptPushCallerBool);
+
+ VARSTR(NPPVpluginKeepLibraryInMemory);
+ VARSTR(NPPVpluginNeedsXEmbed);
+
+ VARSTR(NPPVpluginScriptableNPObject);
+
+ VARSTR(NPPVformValue);
+
+ VARSTR(NPPVpluginUrlRequestsDisplayedBool);
+
+ VARSTR(NPPVpluginWantsAllNetworkStreams);
+
+#ifdef XP_MACOSX
+ VARSTR(NPPVpluginDrawingModel);
+ VARSTR(NPPVpluginEventModel);
+#endif
+
+#ifdef XP_WIN
+ VARSTR(NPPVpluginRequiresAudioDeviceChanges);
+#endif
+
+ default: return "???";
+ }
+}
+
+inline const char*
+NPNVariableToString(NPNVariable aVar)
+{
+ switch(aVar) {
+ VARSTR(NPNVxDisplay);
+ VARSTR(NPNVxtAppContext);
+ VARSTR(NPNVnetscapeWindow);
+ VARSTR(NPNVjavascriptEnabledBool);
+ VARSTR(NPNVasdEnabledBool);
+ VARSTR(NPNVisOfflineBool);
+
+ VARSTR(NPNVserviceManager);
+ VARSTR(NPNVDOMElement);
+ VARSTR(NPNVDOMWindow);
+ VARSTR(NPNVToolkit);
+ VARSTR(NPNVSupportsXEmbedBool);
+
+ VARSTR(NPNVWindowNPObject);
+
+ VARSTR(NPNVPluginElementNPObject);
+
+ VARSTR(NPNVSupportsWindowless);
+
+ VARSTR(NPNVprivateModeBool);
+ VARSTR(NPNVdocumentOrigin);
+
+#ifdef XP_WIN
+ VARSTR(NPNVaudioDeviceChangeDetails);
+#endif
+
+ default: return "???";
+ }
+}
+#undef VARSTR
+
+inline bool IsPluginThread()
+{
+ MessageLoop* loop = MessageLoop::current();
+ if (!loop)
+ return false;
+ return (loop->type() == MessageLoop::TYPE_UI);
+}
+
+inline void AssertPluginThread()
+{
+ MOZ_RELEASE_ASSERT(IsPluginThread(), "Should be on the plugin's main thread!");
+}
+
+#define ENSURE_PLUGIN_THREAD(retval) \
+ PR_BEGIN_MACRO \
+ if (!IsPluginThread()) { \
+ NS_WARNING("Not running on the plugin's main thread!"); \
+ return (retval); \
+ } \
+ PR_END_MACRO
+
+#define ENSURE_PLUGIN_THREAD_VOID() \
+ PR_BEGIN_MACRO \
+ if (!IsPluginThread()) { \
+ NS_WARNING("Not running on the plugin's main thread!"); \
+ return; \
+ } \
+ PR_END_MACRO
+
+void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o);
+void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v);
+
+inline bool IsDrawingModelDirect(int16_t aModel)
+{
+ return aModel == NPDrawingModelAsyncBitmapSurface
+#if defined(XP_WIN)
+ || aModel == NPDrawingModelAsyncWindowsDXGISurface
+#endif
+ ;
+}
+
+// in NPAPI, char* == nullptr is sometimes meaningful. the following is
+// helper code for dealing with nullable nsCString's
+inline nsCString
+NullableString(const char* aString)
+{
+ if (!aString) {
+ return NullCString();
+ }
+ return nsCString(aString);
+}
+
+inline const char*
+NullableStringGet(const nsCString& str)
+{
+ if (str.IsVoid())
+ return nullptr;
+
+ return str.get();
+}
+
+struct DeletingObjectEntry : public nsPtrHashKey<NPObject>
+{
+ explicit DeletingObjectEntry(const NPObject* key)
+ : nsPtrHashKey<NPObject>(key)
+ , mDeleted(false)
+ { }
+
+ bool mDeleted;
+};
+
+} /* namespace plugins */
+
+} /* namespace mozilla */
+
+namespace IPC {
+
+template <>
+struct ParamTraits<NPRect>
+{
+ typedef NPRect paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.top);
+ WriteParam(aMsg, aParam.left);
+ WriteParam(aMsg, aParam.bottom);
+ WriteParam(aMsg, aParam.right);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ uint16_t top, left, bottom, right;
+ if (ReadParam(aMsg, aIter, &top) &&
+ ReadParam(aMsg, aIter, &left) &&
+ ReadParam(aMsg, aIter, &bottom) &&
+ ReadParam(aMsg, aIter, &right)) {
+ aResult->top = top;
+ aResult->left = left;
+ aResult->bottom = bottom;
+ aResult->right = right;
+ return true;
+ }
+ return false;
+ }
+
+ static void Log(const paramType& aParam, std::wstring* aLog)
+ {
+ aLog->append(StringPrintf(L"[%u, %u, %u, %u]", aParam.top, aParam.left,
+ aParam.bottom, aParam.right));
+ }
+};
+
+template <>
+struct ParamTraits<NPWindowType>
+{
+ typedef NPWindowType paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ aMsg->WriteInt16(int16_t(aParam));
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ int16_t result;
+ if (aMsg->ReadInt16(aIter, &result)) {
+ *aResult = paramType(result);
+ return true;
+ }
+ return false;
+ }
+
+ static void Log(const paramType& aParam, std::wstring* aLog)
+ {
+ aLog->append(StringPrintf(L"%d", int16_t(aParam)));
+ }
+};
+
+template <>
+struct ParamTraits<mozilla::plugins::NPRemoteWindow>
+{
+ typedef mozilla::plugins::NPRemoteWindow paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ aMsg->WriteUInt64(aParam.window);
+ WriteParam(aMsg, aParam.x);
+ WriteParam(aMsg, aParam.y);
+ WriteParam(aMsg, aParam.width);
+ WriteParam(aMsg, aParam.height);
+ WriteParam(aMsg, aParam.clipRect);
+ WriteParam(aMsg, aParam.type);
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+ aMsg->WriteULong(aParam.visualID);
+ aMsg->WriteULong(aParam.colormap);
+#endif
+#if defined(XP_MACOSX) || defined(XP_WIN)
+ aMsg->WriteDouble(aParam.contentsScaleFactor);
+#endif
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ uint64_t window;
+ int32_t x, y;
+ uint32_t width, height;
+ NPRect clipRect;
+ NPWindowType type;
+ if (!(aMsg->ReadUInt64(aIter, &window) &&
+ ReadParam(aMsg, aIter, &x) &&
+ ReadParam(aMsg, aIter, &y) &&
+ ReadParam(aMsg, aIter, &width) &&
+ ReadParam(aMsg, aIter, &height) &&
+ ReadParam(aMsg, aIter, &clipRect) &&
+ ReadParam(aMsg, aIter, &type)))
+ return false;
+
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+ unsigned long visualID;
+ unsigned long colormap;
+ if (!(aMsg->ReadULong(aIter, &visualID) &&
+ aMsg->ReadULong(aIter, &colormap)))
+ return false;
+#endif
+
+#if defined(XP_MACOSX) || defined(XP_WIN)
+ double contentsScaleFactor;
+ if (!aMsg->ReadDouble(aIter, &contentsScaleFactor))
+ return false;
+#endif
+
+ aResult->window = window;
+ aResult->x = x;
+ aResult->y = y;
+ aResult->width = width;
+ aResult->height = height;
+ aResult->clipRect = clipRect;
+ aResult->type = type;
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+ aResult->visualID = visualID;
+ aResult->colormap = colormap;
+#endif
+#if defined(XP_MACOSX) || defined(XP_WIN)
+ aResult->contentsScaleFactor = contentsScaleFactor;
+#endif
+ return true;
+ }
+
+ static void Log(const paramType& aParam, std::wstring* aLog)
+ {
+ aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d",
+ (unsigned long)aParam.window,
+ aParam.x, aParam.y, aParam.width,
+ aParam.height, (long)aParam.type));
+ }
+};
+
+#ifdef XP_MACOSX
+template <>
+struct ParamTraits<NPNSString*>
+{
+ typedef NPNSString* paramType;
+
+ // Empty string writes a length of 0 and no buffer.
+ // We don't write a nullptr terminating character in buffers.
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ CFStringRef cfString = (CFStringRef)aParam;
+
+ // Write true if we have a string, false represents nullptr.
+ aMsg->WriteBool(!!cfString);
+ if (!cfString) {
+ return;
+ }
+
+ long length = ::CFStringGetLength(cfString);
+ WriteParam(aMsg, length);
+ if (length == 0) {
+ return;
+ }
+
+ // Attempt to get characters without any allocation/conversion.
+ if (::CFStringGetCharactersPtr(cfString)) {
+ aMsg->WriteBytes(::CFStringGetCharactersPtr(cfString), length * sizeof(UniChar));
+ } else {
+ UniChar *buffer = (UniChar*)moz_xmalloc(length * sizeof(UniChar));
+ ::CFStringGetCharacters(cfString, ::CFRangeMake(0, length), buffer);
+ aMsg->WriteBytes(buffer, length * sizeof(UniChar));
+ free(buffer);
+ }
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ bool haveString = false;
+ if (!aMsg->ReadBool(aIter, &haveString)) {
+ return false;
+ }
+ if (!haveString) {
+ *aResult = nullptr;
+ return true;
+ }
+
+ long length;
+ if (!ReadParam(aMsg, aIter, &length)) {
+ return false;
+ }
+
+ // Avoid integer multiplication overflow.
+ if (length > INT_MAX / static_cast<long>(sizeof(UniChar))) {
+ return false;
+ }
+
+ auto chars = mozilla::MakeUnique<UniChar[]>(length);
+ if (length != 0) {
+ if (!aMsg->ReadBytesInto(aIter, chars.get(), length * sizeof(UniChar))) {
+ return false;
+ }
+ }
+
+ *aResult = (NPNSString*)::CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)chars.get(),
+ length * sizeof(UniChar),
+ kCFStringEncodingUTF16, false);
+ if (!*aResult) {
+ return false;
+ }
+
+ return true;
+ }
+};
+#endif
+
+#ifdef XP_MACOSX
+template <>
+struct ParamTraits<NSCursorInfo>
+{
+ typedef NSCursorInfo paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ NSCursorInfo::Type type = aParam.GetType();
+
+ aMsg->WriteInt(type);
+
+ nsPoint hotSpot = aParam.GetHotSpot();
+ WriteParam(aMsg, hotSpot.x);
+ WriteParam(aMsg, hotSpot.y);
+
+ uint32_t dataLength = aParam.GetCustomImageDataLength();
+ WriteParam(aMsg, dataLength);
+ if (dataLength == 0) {
+ return;
+ }
+
+ uint8_t* buffer = (uint8_t*)moz_xmalloc(dataLength);
+ memcpy(buffer, aParam.GetCustomImageData(), dataLength);
+ aMsg->WriteBytes(buffer, dataLength);
+ free(buffer);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ NSCursorInfo::Type type;
+ if (!aMsg->ReadInt(aIter, (int*)&type)) {
+ return false;
+ }
+
+ nscoord hotSpotX, hotSpotY;
+ if (!ReadParam(aMsg, aIter, &hotSpotX) ||
+ !ReadParam(aMsg, aIter, &hotSpotY)) {
+ return false;
+ }
+
+ uint32_t dataLength;
+ if (!ReadParam(aMsg, aIter, &dataLength)) {
+ return false;
+ }
+
+ auto data = mozilla::MakeUnique<uint8_t[]>(dataLength);
+ if (dataLength != 0) {
+ if (!aMsg->ReadBytesInto(aIter, data.get(), dataLength)) {
+ return false;
+ }
+ }
+
+ aResult->SetType(type);
+ aResult->SetHotSpot(nsPoint(hotSpotX, hotSpotY));
+ aResult->SetCustomImageData(data.get(), dataLength);
+
+ return true;
+ }
+
+ static void Log(const paramType& aParam, std::wstring* aLog)
+ {
+ const char* typeName = aParam.GetTypeName();
+ nsPoint hotSpot = aParam.GetHotSpot();
+ int hotSpotX, hotSpotY;
+#ifdef NS_COORD_IS_FLOAT
+ hotSpotX = rint(hotSpot.x);
+ hotSpotY = rint(hotSpot.y);
+#else
+ hotSpotX = hotSpot.x;
+ hotSpotY = hotSpot.y;
+#endif
+ uint32_t dataLength = aParam.GetCustomImageDataLength();
+ uint8_t* data = aParam.GetCustomImageData();
+
+ aLog->append(StringPrintf(L"[%s, (%i %i), %u, %p]",
+ typeName, hotSpotX, hotSpotY, dataLength, data));
+ }
+};
+#else
+template<>
+struct ParamTraits<NSCursorInfo>
+{
+ typedef NSCursorInfo paramType;
+ static void Write(Message* aMsg, const paramType& aParam) {
+ NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
+ }
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
+ NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
+ return false;
+ }
+};
+#endif // #ifdef XP_MACOSX
+
+template <>
+struct ParamTraits<mozilla::plugins::IPCByteRange>
+{
+ typedef mozilla::plugins::IPCByteRange paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.offset);
+ WriteParam(aMsg, aParam.length);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ paramType p;
+ if (ReadParam(aMsg, aIter, &p.offset) &&
+ ReadParam(aMsg, aIter, &p.length)) {
+ *aResult = p;
+ return true;
+ }
+ return false;
+ }
+};
+
+template <>
+struct ParamTraits<NPNVariable>
+{
+ typedef NPNVariable paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, int(aParam));
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ int intval;
+ if (ReadParam(aMsg, aIter, &intval)) {
+ *aResult = paramType(intval);
+ return true;
+ }
+ return false;
+ }
+};
+
+template<>
+struct ParamTraits<NPNURLVariable>
+{
+ typedef NPNURLVariable paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, int(aParam));
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ int intval;
+ if (ReadParam(aMsg, aIter, &intval)) {
+ switch (intval) {
+ case NPNURLVCookie:
+ case NPNURLVProxy:
+ *aResult = paramType(intval);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+
+template<>
+struct ParamTraits<NPCoordinateSpace>
+{
+ typedef NPCoordinateSpace paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, int32_t(aParam));
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ int32_t intval;
+ if (ReadParam(aMsg, aIter, &intval)) {
+ switch (intval) {
+ case NPCoordinateSpacePlugin:
+ case NPCoordinateSpaceWindow:
+ case NPCoordinateSpaceFlippedWindow:
+ case NPCoordinateSpaceScreen:
+ case NPCoordinateSpaceFlippedScreen:
+ *aResult = paramType(intval);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+template <>
+struct ParamTraits<mozilla::plugins::NPAudioDeviceChangeDetailsIPC>
+{
+ typedef mozilla::plugins::NPAudioDeviceChangeDetailsIPC paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.flow);
+ WriteParam(aMsg, aParam.role);
+ WriteParam(aMsg, aParam.defaultDevice);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ int32_t flow, role;
+ std::wstring defaultDevice;
+ if (ReadParam(aMsg, aIter, &flow) &&
+ ReadParam(aMsg, aIter, &role) &&
+ ReadParam(aMsg, aIter, &defaultDevice)) {
+ aResult->flow = flow;
+ aResult->role = role;
+ aResult->defaultDevice = defaultDevice;
+ return true;
+ }
+ return false;
+ }
+
+ static void Log(const paramType& aParam, std::wstring* aLog)
+ {
+ aLog->append(StringPrintf(L"[%d, %d, %S]", aParam.flow, aParam.role,
+ aParam.defaultDevice.c_str()));
+ }
+};
+
+} /* namespace IPC */
+
+
+// Serializing NPEvents is completely platform-specific and can be rather
+// intricate depending on the platform. So for readability we split it
+// into separate files and have the only macro crud live here.
+//
+// NB: these guards are based on those where struct NPEvent is defined
+// in npapi.h. They should be kept in sync.
+#if defined(XP_MACOSX)
+# include "mozilla/plugins/NPEventOSX.h"
+#elif defined(XP_WIN)
+# include "mozilla/plugins/NPEventWindows.h"
+#elif defined(ANDROID)
+# include "mozilla/plugins/NPEventAndroid.h"
+#elif defined(XP_UNIX)
+# include "mozilla/plugins/NPEventUnix.h"
+#else
+# error Unsupported platform
+#endif
+
+#endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */