/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * 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" namespace mac_plugin_interposing { class NSCursorInfo { }; } 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 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) VisualID visualID; Colormap colormap; #endif /* XP_UNIX */ #if 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; #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_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 { explicit DeletingObjectEntry(const NPObject* key) : nsPtrHashKey(key) , mDeleted(false) { } bool mDeleted; }; } /* namespace plugins */ } /* namespace mozilla */ namespace IPC { template <> struct ParamTraits { 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 { 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 { 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) aMsg->WriteULong(aParam.visualID); aMsg->WriteULong(aParam.colormap); #endif #if 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) unsigned long visualID; unsigned long colormap; if (!(aMsg->ReadULong(aIter, &visualID) && aMsg->ReadULong(aIter, &colormap))) return false; #endif #if 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) aResult->visualID = visualID; aResult->colormap = colormap; #endif #if 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)); } }; template<> struct ParamTraits { 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; } }; template <> struct ParamTraits { 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 { 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 { 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 { 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 { 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_WIN) # include "mozilla/plugins/NPEventWindows.h" #elif defined(XP_UNIX) # include "mozilla/plugins/NPEventUnix.h" #else # error Unsupported platform #endif #endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */