michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=4 ts=4 et : michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef DOM_PLUGINS_PLUGINMESSAGEUTILS_H michael@0: #define DOM_PLUGINS_PLUGINMESSAGEUTILS_H michael@0: michael@0: #include "ipc/IPCMessageUtils.h" michael@0: #include "base/message_loop.h" michael@0: michael@0: #include "mozilla/ipc/MessageChannel.h" michael@0: #include "mozilla/ipc/CrossProcessMutex.h" michael@0: #include "gfxipc/ShadowLayerUtils.h" michael@0: michael@0: #include "npapi.h" michael@0: #include "npruntime.h" michael@0: #include "npfunctions.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsString.h" michael@0: #include "nsTArray.h" michael@0: #include "prlog.h" michael@0: #include "nsHashKeys.h" michael@0: #ifdef MOZ_CRASHREPORTER michael@0: # include "nsExceptionHandler.h" michael@0: #endif michael@0: #ifdef XP_MACOSX michael@0: #include "PluginInterposeOSX.h" michael@0: #else michael@0: namespace mac_plugin_interposing { class NSCursorInfo { }; } michael@0: #endif michael@0: using mac_plugin_interposing::NSCursorInfo; michael@0: michael@0: namespace mozilla { michael@0: namespace plugins { michael@0: michael@0: using layers::SurfaceDescriptorX11; michael@0: michael@0: enum ScriptableObjectType michael@0: { michael@0: LocalObject, michael@0: Proxy michael@0: }; michael@0: michael@0: mozilla::ipc::RacyInterruptPolicy michael@0: MediateRace(const mozilla::ipc::MessageChannel::Message& parent, michael@0: const mozilla::ipc::MessageChannel::Message& child); michael@0: michael@0: std::string michael@0: MungePluginDsoPath(const std::string& path); michael@0: std::string michael@0: UnmungePluginDsoPath(const std::string& munged); michael@0: michael@0: extern PRLogModuleInfo* GetPluginLog(); michael@0: michael@0: const uint32_t kAllowAsyncDrawing = 0x1; michael@0: michael@0: inline bool IsDrawingModelAsync(int16_t aModel) { michael@0: return aModel == NPDrawingModelAsyncBitmapSurface michael@0: #ifdef XP_WIN michael@0: || aModel == NPDrawingModelAsyncWindowsDXGISurface michael@0: #endif michael@0: ; michael@0: } michael@0: michael@0: #if defined(_MSC_VER) michael@0: #define FULLFUNCTION __FUNCSIG__ michael@0: #elif defined(__GNUC__) michael@0: #define FULLFUNCTION __PRETTY_FUNCTION__ michael@0: #else michael@0: #define FULLFUNCTION __FUNCTION__ michael@0: #endif michael@0: michael@0: #define PLUGIN_LOG_DEBUG(args) PR_LOG(GetPluginLog(), PR_LOG_DEBUG, args) michael@0: #define PLUGIN_LOG_DEBUG_FUNCTION PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION)) michael@0: #define PLUGIN_LOG_DEBUG_METHOD PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s [%p]", FULLFUNCTION, (void*) this)) michael@0: michael@0: /** michael@0: * This is NPByteRange without the linked list. michael@0: */ michael@0: struct IPCByteRange michael@0: { michael@0: int32_t offset; michael@0: uint32_t length; michael@0: }; michael@0: michael@0: typedef std::vector IPCByteRanges; michael@0: michael@0: typedef nsCString Buffer; michael@0: michael@0: struct NPRemoteWindow michael@0: { michael@0: NPRemoteWindow(); michael@0: uint64_t window; michael@0: int32_t x; michael@0: int32_t y; michael@0: uint32_t width; michael@0: uint32_t height; michael@0: NPRect clipRect; michael@0: NPWindowType type; michael@0: #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) michael@0: VisualID visualID; michael@0: Colormap colormap; michael@0: #endif /* XP_UNIX */ michael@0: #if defined(XP_WIN) michael@0: base::SharedMemoryHandle surfaceHandle; michael@0: #endif michael@0: #if defined(XP_MACOSX) michael@0: double contentsScaleFactor; michael@0: #endif michael@0: }; michael@0: michael@0: #ifdef XP_WIN michael@0: typedef HWND NativeWindowHandle; michael@0: #elif defined(MOZ_X11) michael@0: typedef XID NativeWindowHandle; michael@0: #elif defined(XP_MACOSX) || defined(ANDROID) || defined(MOZ_WIDGET_QT) michael@0: typedef intptr_t NativeWindowHandle; // never actually used, will always be 0 michael@0: #else michael@0: #error Need NativeWindowHandle for this platform michael@0: #endif michael@0: michael@0: #ifdef XP_WIN michael@0: typedef base::SharedMemoryHandle WindowsSharedMemoryHandle; michael@0: typedef HANDLE DXGISharedSurfaceHandle; michael@0: #else michael@0: typedef mozilla::null_t WindowsSharedMemoryHandle; michael@0: typedef mozilla::null_t DXGISharedSurfaceHandle; michael@0: #endif michael@0: michael@0: // XXX maybe not the best place for these. better one? michael@0: michael@0: #define VARSTR(v_) case v_: return #v_ michael@0: inline const char* const michael@0: NPPVariableToString(NPPVariable aVar) michael@0: { michael@0: switch (aVar) { michael@0: VARSTR(NPPVpluginNameString); michael@0: VARSTR(NPPVpluginDescriptionString); michael@0: VARSTR(NPPVpluginWindowBool); michael@0: VARSTR(NPPVpluginTransparentBool); michael@0: VARSTR(NPPVjavaClass); michael@0: VARSTR(NPPVpluginWindowSize); michael@0: VARSTR(NPPVpluginTimerInterval); michael@0: michael@0: VARSTR(NPPVpluginScriptableInstance); michael@0: VARSTR(NPPVpluginScriptableIID); michael@0: michael@0: VARSTR(NPPVjavascriptPushCallerBool); michael@0: michael@0: VARSTR(NPPVpluginKeepLibraryInMemory); michael@0: VARSTR(NPPVpluginNeedsXEmbed); michael@0: michael@0: VARSTR(NPPVpluginScriptableNPObject); michael@0: michael@0: VARSTR(NPPVformValue); michael@0: michael@0: VARSTR(NPPVpluginUrlRequestsDisplayedBool); michael@0: michael@0: VARSTR(NPPVpluginWantsAllNetworkStreams); michael@0: michael@0: #ifdef XP_MACOSX michael@0: VARSTR(NPPVpluginDrawingModel); michael@0: VARSTR(NPPVpluginEventModel); michael@0: #endif michael@0: michael@0: default: return "???"; michael@0: } michael@0: } michael@0: michael@0: inline const char* michael@0: NPNVariableToString(NPNVariable aVar) michael@0: { michael@0: switch(aVar) { michael@0: VARSTR(NPNVxDisplay); michael@0: VARSTR(NPNVxtAppContext); michael@0: VARSTR(NPNVnetscapeWindow); michael@0: VARSTR(NPNVjavascriptEnabledBool); michael@0: VARSTR(NPNVasdEnabledBool); michael@0: VARSTR(NPNVisOfflineBool); michael@0: michael@0: VARSTR(NPNVserviceManager); michael@0: VARSTR(NPNVDOMElement); michael@0: VARSTR(NPNVDOMWindow); michael@0: VARSTR(NPNVToolkit); michael@0: VARSTR(NPNVSupportsXEmbedBool); michael@0: michael@0: VARSTR(NPNVWindowNPObject); michael@0: michael@0: VARSTR(NPNVPluginElementNPObject); michael@0: michael@0: VARSTR(NPNVSupportsWindowless); michael@0: michael@0: VARSTR(NPNVprivateModeBool); michael@0: VARSTR(NPNVdocumentOrigin); michael@0: michael@0: default: return "???"; michael@0: } michael@0: } michael@0: #undef VARSTR michael@0: michael@0: inline bool IsPluginThread() michael@0: { michael@0: MessageLoop* loop = MessageLoop::current(); michael@0: if (!loop) michael@0: return false; michael@0: return (loop->type() == MessageLoop::TYPE_UI); michael@0: } michael@0: michael@0: inline void AssertPluginThread() michael@0: { michael@0: NS_ASSERTION(IsPluginThread(), "Should be on the plugin's main thread!"); michael@0: } michael@0: michael@0: #define ENSURE_PLUGIN_THREAD(retval) \ michael@0: PR_BEGIN_MACRO \ michael@0: if (!IsPluginThread()) { \ michael@0: NS_WARNING("Not running on the plugin's main thread!"); \ michael@0: return (retval); \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: #define ENSURE_PLUGIN_THREAD_VOID() \ michael@0: PR_BEGIN_MACRO \ michael@0: if (!IsPluginThread()) { \ michael@0: NS_WARNING("Not running on the plugin's main thread!"); \ michael@0: return; \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o); michael@0: void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v); michael@0: michael@0: // in NPAPI, char* == nullptr is sometimes meaningful. the following is michael@0: // helper code for dealing with nullable nsCString's michael@0: inline nsCString michael@0: NullableString(const char* aString) michael@0: { michael@0: if (!aString) { michael@0: nsCString str; michael@0: str.SetIsVoid(true); michael@0: return str; michael@0: } michael@0: return nsCString(aString); michael@0: } michael@0: michael@0: inline const char* michael@0: NullableStringGet(const nsCString& str) michael@0: { michael@0: if (str.IsVoid()) michael@0: return nullptr; michael@0: michael@0: return str.get(); michael@0: } michael@0: michael@0: struct DeletingObjectEntry : public nsPtrHashKey michael@0: { michael@0: DeletingObjectEntry(const NPObject* key) michael@0: : nsPtrHashKey(key) michael@0: , mDeleted(false) michael@0: { } michael@0: michael@0: bool mDeleted; michael@0: }; michael@0: michael@0: #ifdef XP_WIN michael@0: // The private event used for double-pass widgetless plugin rendering. michael@0: UINT DoublePassRenderingEvent(); michael@0: #endif michael@0: michael@0: } /* namespace plugins */ michael@0: michael@0: } /* namespace mozilla */ michael@0: michael@0: namespace IPC { michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPRect paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.top); michael@0: WriteParam(aMsg, aParam.left); michael@0: WriteParam(aMsg, aParam.bottom); michael@0: WriteParam(aMsg, aParam.right); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: uint16_t top, left, bottom, right; michael@0: if (ReadParam(aMsg, aIter, &top) && michael@0: ReadParam(aMsg, aIter, &left) && michael@0: ReadParam(aMsg, aIter, &bottom) && michael@0: ReadParam(aMsg, aIter, &right)) { michael@0: aResult->top = top; michael@0: aResult->left = left; michael@0: aResult->bottom = bottom; michael@0: aResult->right = right; michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"[%u, %u, %u, %u]", aParam.top, aParam.left, michael@0: aParam.bottom, aParam.right)); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPWindowType paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteInt16(int16_t(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int16_t result; michael@0: if (aMsg->ReadInt16(aIter, &result)) { michael@0: *aResult = paramType(result); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"%d", int16_t(aParam))); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPImageFormat paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteInt16(int16_t(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int16_t result; michael@0: if (aMsg->ReadInt16(aIter, &result)) { michael@0: *aResult = paramType(result); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"%d", int16_t(aParam))); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::plugins::NPRemoteWindow paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: aMsg->WriteUInt64(aParam.window); michael@0: WriteParam(aMsg, aParam.x); michael@0: WriteParam(aMsg, aParam.y); michael@0: WriteParam(aMsg, aParam.width); michael@0: WriteParam(aMsg, aParam.height); michael@0: WriteParam(aMsg, aParam.clipRect); michael@0: WriteParam(aMsg, aParam.type); michael@0: #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) michael@0: aMsg->WriteULong(aParam.visualID); michael@0: aMsg->WriteULong(aParam.colormap); michael@0: #endif michael@0: #if defined(XP_WIN) michael@0: WriteParam(aMsg, aParam.surfaceHandle); michael@0: #endif michael@0: #if defined(XP_MACOSX) michael@0: aMsg->WriteDouble(aParam.contentsScaleFactor); michael@0: #endif michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: uint64_t window; michael@0: int32_t x, y; michael@0: uint32_t width, height; michael@0: NPRect clipRect; michael@0: NPWindowType type; michael@0: if (!(aMsg->ReadUInt64(aIter, &window) && michael@0: ReadParam(aMsg, aIter, &x) && michael@0: ReadParam(aMsg, aIter, &y) && michael@0: ReadParam(aMsg, aIter, &width) && michael@0: ReadParam(aMsg, aIter, &height) && michael@0: ReadParam(aMsg, aIter, &clipRect) && michael@0: ReadParam(aMsg, aIter, &type))) michael@0: return false; michael@0: michael@0: #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) michael@0: unsigned long visualID; michael@0: unsigned long colormap; michael@0: if (!(aMsg->ReadULong(aIter, &visualID) && michael@0: aMsg->ReadULong(aIter, &colormap))) michael@0: return false; michael@0: #endif michael@0: michael@0: #if defined(XP_WIN) michael@0: base::SharedMemoryHandle surfaceHandle; michael@0: if (!ReadParam(aMsg, aIter, &surfaceHandle)) michael@0: return false; michael@0: #endif michael@0: michael@0: #if defined(XP_MACOSX) michael@0: double contentsScaleFactor; michael@0: if (!aMsg->ReadDouble(aIter, &contentsScaleFactor)) michael@0: return false; michael@0: #endif michael@0: michael@0: aResult->window = window; michael@0: aResult->x = x; michael@0: aResult->y = y; michael@0: aResult->width = width; michael@0: aResult->height = height; michael@0: aResult->clipRect = clipRect; michael@0: aResult->type = type; michael@0: #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) michael@0: aResult->visualID = visualID; michael@0: aResult->colormap = colormap; michael@0: #endif michael@0: #if defined(XP_WIN) michael@0: aResult->surfaceHandle = surfaceHandle; michael@0: #endif michael@0: #if defined(XP_MACOSX) michael@0: aResult->contentsScaleFactor = contentsScaleFactor; michael@0: #endif michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d", michael@0: (unsigned long)aParam.window, michael@0: aParam.x, aParam.y, aParam.width, michael@0: aParam.height, (long)aParam.type)); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPString paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.UTF8Length); michael@0: aMsg->WriteBytes(aParam.UTF8Characters, michael@0: aParam.UTF8Length * sizeof(NPUTF8)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: if (ReadParam(aMsg, aIter, &aResult->UTF8Length)) { michael@0: int byteCount = aResult->UTF8Length * sizeof(NPUTF8); michael@0: if (!byteCount) { michael@0: aResult->UTF8Characters = "\0"; michael@0: return true; michael@0: } michael@0: michael@0: const char* messageBuffer = nullptr; michael@0: nsAutoArrayPtr newBuffer(new char[byteCount]); michael@0: if (newBuffer && aMsg->ReadBytes(aIter, &messageBuffer, byteCount )) { michael@0: memcpy((void*)messageBuffer, newBuffer.get(), byteCount); michael@0: aResult->UTF8Characters = newBuffer.forget(); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: aLog->append(StringPrintf(L"%s", aParam.UTF8Characters)); michael@0: } michael@0: }; michael@0: michael@0: #ifdef XP_MACOSX michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPNSString* paramType; michael@0: michael@0: // Empty string writes a length of 0 and no buffer. michael@0: // We don't write a nullptr terminating character in buffers. michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: CFStringRef cfString = (CFStringRef)aParam; michael@0: michael@0: // Write true if we have a string, false represents nullptr. michael@0: aMsg->WriteBool(!!cfString); michael@0: if (!cfString) { michael@0: return; michael@0: } michael@0: michael@0: long length = ::CFStringGetLength(cfString); michael@0: WriteParam(aMsg, length); michael@0: if (length == 0) { michael@0: return; michael@0: } michael@0: michael@0: // Attempt to get characters without any allocation/conversion. michael@0: if (::CFStringGetCharactersPtr(cfString)) { michael@0: aMsg->WriteBytes(::CFStringGetCharactersPtr(cfString), length * sizeof(UniChar)); michael@0: } else { michael@0: UniChar *buffer = (UniChar*)moz_xmalloc(length * sizeof(UniChar)); michael@0: ::CFStringGetCharacters(cfString, ::CFRangeMake(0, length), buffer); michael@0: aMsg->WriteBytes(buffer, length * sizeof(UniChar)); michael@0: free(buffer); michael@0: } michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: bool haveString = false; michael@0: if (!aMsg->ReadBool(aIter, &haveString)) { michael@0: return false; michael@0: } michael@0: if (!haveString) { michael@0: *aResult = nullptr; michael@0: return true; michael@0: } michael@0: michael@0: long length; michael@0: if (!ReadParam(aMsg, aIter, &length)) { michael@0: return false; michael@0: } michael@0: michael@0: UniChar* buffer = nullptr; michael@0: if (length != 0) { michael@0: if (!aMsg->ReadBytes(aIter, (const char**)&buffer, length * sizeof(UniChar)) || michael@0: !buffer) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: *aResult = (NPNSString*)::CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)buffer, michael@0: length * sizeof(UniChar), michael@0: kCFStringEncodingUTF16, false); michael@0: if (!*aResult) { michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: }; michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NSCursorInfo paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: NSCursorInfo::Type type = aParam.GetType(); michael@0: michael@0: aMsg->WriteInt(type); michael@0: michael@0: nsPoint hotSpot = aParam.GetHotSpot(); michael@0: WriteParam(aMsg, hotSpot.x); michael@0: WriteParam(aMsg, hotSpot.y); michael@0: michael@0: uint32_t dataLength = aParam.GetCustomImageDataLength(); michael@0: WriteParam(aMsg, dataLength); michael@0: if (dataLength == 0) { michael@0: return; michael@0: } michael@0: michael@0: uint8_t* buffer = (uint8_t*)moz_xmalloc(dataLength); michael@0: memcpy(buffer, aParam.GetCustomImageData(), dataLength); michael@0: aMsg->WriteBytes(buffer, dataLength); michael@0: free(buffer); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: NSCursorInfo::Type type; michael@0: if (!aMsg->ReadInt(aIter, (int*)&type)) { michael@0: return false; michael@0: } michael@0: michael@0: nscoord hotSpotX, hotSpotY; michael@0: if (!ReadParam(aMsg, aIter, &hotSpotX) || michael@0: !ReadParam(aMsg, aIter, &hotSpotY)) { michael@0: return false; michael@0: } michael@0: michael@0: uint32_t dataLength; michael@0: if (!ReadParam(aMsg, aIter, &dataLength)) { michael@0: return false; michael@0: } michael@0: michael@0: uint8_t* data = nullptr; michael@0: if (dataLength != 0) { michael@0: if (!aMsg->ReadBytes(aIter, (const char**)&data, dataLength) || !data) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: aResult->SetType(type); michael@0: aResult->SetHotSpot(nsPoint(hotSpotX, hotSpotY)); michael@0: aResult->SetCustomImageData(data, dataLength); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: const char* typeName = aParam.GetTypeName(); michael@0: nsPoint hotSpot = aParam.GetHotSpot(); michael@0: int hotSpotX, hotSpotY; michael@0: #ifdef NS_COORD_IS_FLOAT michael@0: hotSpotX = rint(hotSpot.x); michael@0: hotSpotY = rint(hotSpot.y); michael@0: #else michael@0: hotSpotX = hotSpot.x; michael@0: hotSpotY = hotSpot.y; michael@0: #endif michael@0: uint32_t dataLength = aParam.GetCustomImageDataLength(); michael@0: uint8_t* data = aParam.GetCustomImageData(); michael@0: michael@0: aLog->append(StringPrintf(L"[%s, (%i %i), %u, %p]", michael@0: typeName, hotSpotX, hotSpotY, dataLength, data)); michael@0: } michael@0: }; michael@0: #else michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef NSCursorInfo paramType; michael@0: static void Write(Message* aMsg, const paramType& aParam) { michael@0: NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform"); michael@0: } michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { michael@0: NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform"); michael@0: return false; michael@0: } michael@0: }; michael@0: #endif // #ifdef XP_MACOSX michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPVariant paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: if (NPVARIANT_IS_VOID(aParam)) { michael@0: aMsg->WriteInt(0); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_NULL(aParam)) { michael@0: aMsg->WriteInt(1); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_BOOLEAN(aParam)) { michael@0: aMsg->WriteInt(2); michael@0: WriteParam(aMsg, NPVARIANT_TO_BOOLEAN(aParam)); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_INT32(aParam)) { michael@0: aMsg->WriteInt(3); michael@0: WriteParam(aMsg, NPVARIANT_TO_INT32(aParam)); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_DOUBLE(aParam)) { michael@0: aMsg->WriteInt(4); michael@0: WriteParam(aMsg, NPVARIANT_TO_DOUBLE(aParam)); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_STRING(aParam)) { michael@0: aMsg->WriteInt(5); michael@0: WriteParam(aMsg, NPVARIANT_TO_STRING(aParam)); michael@0: return; michael@0: } michael@0: michael@0: NS_ERROR("Unsupported type!"); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int type; michael@0: if (!aMsg->ReadInt(aIter, &type)) { michael@0: return false; michael@0: } michael@0: michael@0: switch (type) { michael@0: case 0: michael@0: VOID_TO_NPVARIANT(*aResult); michael@0: return true; michael@0: michael@0: case 1: michael@0: NULL_TO_NPVARIANT(*aResult); michael@0: return true; michael@0: michael@0: case 2: { michael@0: bool value; michael@0: if (ReadParam(aMsg, aIter, &value)) { michael@0: BOOLEAN_TO_NPVARIANT(value, *aResult); michael@0: return true; michael@0: } michael@0: } break; michael@0: michael@0: case 3: { michael@0: int32_t value; michael@0: if (ReadParam(aMsg, aIter, &value)) { michael@0: INT32_TO_NPVARIANT(value, *aResult); michael@0: return true; michael@0: } michael@0: } break; michael@0: michael@0: case 4: { michael@0: double value; michael@0: if (ReadParam(aMsg, aIter, &value)) { michael@0: DOUBLE_TO_NPVARIANT(value, *aResult); michael@0: return true; michael@0: } michael@0: } break; michael@0: michael@0: case 5: { michael@0: NPString value; michael@0: if (ReadParam(aMsg, aIter, &value)) { michael@0: STRINGN_TO_NPVARIANT(value.UTF8Characters, value.UTF8Length, michael@0: *aResult); michael@0: return true; michael@0: } michael@0: } break; michael@0: michael@0: default: michael@0: NS_ERROR("Unsupported type!"); michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: static void Log(const paramType& aParam, std::wstring* aLog) michael@0: { michael@0: if (NPVARIANT_IS_VOID(aParam)) { michael@0: aLog->append(L"[void]"); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_NULL(aParam)) { michael@0: aLog->append(L"[null]"); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_BOOLEAN(aParam)) { michael@0: LogParam(NPVARIANT_TO_BOOLEAN(aParam), aLog); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_INT32(aParam)) { michael@0: LogParam(NPVARIANT_TO_INT32(aParam), aLog); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_DOUBLE(aParam)) { michael@0: LogParam(NPVARIANT_TO_DOUBLE(aParam), aLog); michael@0: return; michael@0: } michael@0: michael@0: if (NPVARIANT_IS_STRING(aParam)) { michael@0: LogParam(NPVARIANT_TO_STRING(aParam), aLog); michael@0: return; michael@0: } michael@0: michael@0: NS_ERROR("Unsupported type!"); michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef mozilla::plugins::IPCByteRange paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, aParam.offset); michael@0: WriteParam(aMsg, aParam.length); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: paramType p; michael@0: if (ReadParam(aMsg, aIter, &p.offset) && michael@0: ReadParam(aMsg, aIter, &p.length)) { michael@0: *aResult = p; michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: }; michael@0: michael@0: template <> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPNVariable paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, int(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int intval; michael@0: if (ReadParam(aMsg, aIter, &intval)) { michael@0: *aResult = paramType(intval); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPNURLVariable paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, int(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int intval; michael@0: if (ReadParam(aMsg, aIter, &intval)) { michael@0: switch (intval) { michael@0: case NPNURLVCookie: michael@0: case NPNURLVProxy: michael@0: *aResult = paramType(intval); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: }; michael@0: michael@0: michael@0: template<> michael@0: struct ParamTraits michael@0: { michael@0: typedef NPCoordinateSpace paramType; michael@0: michael@0: static void Write(Message* aMsg, const paramType& aParam) michael@0: { michael@0: WriteParam(aMsg, int32_t(aParam)); michael@0: } michael@0: michael@0: static bool Read(const Message* aMsg, void** aIter, paramType* aResult) michael@0: { michael@0: int32_t intval; michael@0: if (ReadParam(aMsg, aIter, &intval)) { michael@0: switch (intval) { michael@0: case NPCoordinateSpacePlugin: michael@0: case NPCoordinateSpaceWindow: michael@0: case NPCoordinateSpaceFlippedWindow: michael@0: case NPCoordinateSpaceScreen: michael@0: case NPCoordinateSpaceFlippedScreen: michael@0: *aResult = paramType(intval); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: }; michael@0: michael@0: } /* namespace IPC */ michael@0: michael@0: michael@0: // Serializing NPEvents is completely platform-specific and can be rather michael@0: // intricate depending on the platform. So for readability we split it michael@0: // into separate files and have the only macro crud live here. michael@0: // michael@0: // NB: these guards are based on those where struct NPEvent is defined michael@0: // in npapi.h. They should be kept in sync. michael@0: #if defined(XP_MACOSX) michael@0: # include "mozilla/plugins/NPEventOSX.h" michael@0: #elif defined(XP_WIN) michael@0: # include "mozilla/plugins/NPEventWindows.h" michael@0: #elif defined(ANDROID) michael@0: # include "mozilla/plugins/NPEventAndroid.h" michael@0: #elif defined(XP_UNIX) michael@0: # include "mozilla/plugins/NPEventUnix.h" michael@0: #else michael@0: # error Unsupported platform michael@0: #endif michael@0: michael@0: #endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */