diff options
Diffstat (limited to 'dom/plugins/ipc/hangui/MiniShmBase.h')
-rw-r--r-- | dom/plugins/ipc/hangui/MiniShmBase.h | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/dom/plugins/ipc/hangui/MiniShmBase.h b/dom/plugins/ipc/hangui/MiniShmBase.h new file mode 100644 index 0000000000..9782330b12 --- /dev/null +++ b/dom/plugins/ipc/hangui/MiniShmBase.h @@ -0,0 +1,280 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 mozilla_plugins_MiniShmBase_h +#define mozilla_plugins_MiniShmBase_h + +#include "base/basictypes.h" + +#include "nsDebug.h" + +#include <windows.h> + +namespace mozilla { +namespace plugins { + +/** + * This class is used to provide RAII semantics for mapped views. + * @see ScopedHandle + */ +class ScopedMappedFileView { + public: + explicit ScopedMappedFileView(LPVOID aView) : mView(aView) {} + + ~ScopedMappedFileView() { Close(); } + + void Close() { + if (mView) { + ::UnmapViewOfFile(mView); + mView = nullptr; + } + } + + void Set(LPVOID aView) { + Close(); + mView = aView; + } + + LPVOID + Get() const { return mView; } + + LPVOID + Take() { + LPVOID result = mView; + mView = nullptr; + return result; + } + + operator LPVOID() { return mView; } + + bool IsValid() const { return (mView); } + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedMappedFileView); + + LPVOID mView; +}; + +class MiniShmBase; + +class MiniShmObserver { + public: + /** + * This function is called whenever there is a new shared memory request. + * @param aMiniShmObj MiniShmBase object that may be used to read and + * write from shared memory. + */ + virtual void OnMiniShmEvent(MiniShmBase* aMiniShmObj) = 0; + /** + * This function is called once when a MiniShmParent and a MiniShmChild + * object have successfully negotiated a connection. + * + * @param aMiniShmObj MiniShmBase object that may be used to read and + * write from shared memory. + */ + virtual void OnMiniShmConnect(MiniShmBase* aMiniShmObj) {} +}; + +/** + * Base class for MiniShm connections. This class defines the common + * interfaces and code between parent and child. + */ +class MiniShmBase { + public: + /** + * Obtains a writable pointer into shared memory of type T. + * typename T must be plain-old-data and contain an unsigned integral + * member T::identifier that uniquely identifies T with respect to + * other types used by the protocol being implemented. + * + * @param aPtr Pointer to receive the shared memory address. + * This value is set if and only if the function + * succeeded. + * @return NS_OK if and only if aPtr was successfully obtained. + * NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm. + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. + * NS_ERROR_NOT_AVAILABLE if the memory is not safe to write. + */ + template <typename T> + nsresult GetWritePtr(T*& aPtr) { + if (!mWriteHeader || !mGuard) { + return NS_ERROR_NOT_INITIALIZED; + } + if (sizeof(T) > mPayloadMaxLen || + (int)T::identifier <= (int)RESERVED_CODE_LAST) { + return NS_ERROR_ILLEGAL_VALUE; + } + if (::WaitForSingleObject(mGuard, mTimeout) != WAIT_OBJECT_0) { + return NS_ERROR_NOT_AVAILABLE; + } + mWriteHeader->mId = T::identifier; + mWriteHeader->mPayloadLen = sizeof(T); + aPtr = reinterpret_cast<T*>(mWriteHeader + 1); + return NS_OK; + } + + /** + * Obtains a readable pointer into shared memory of type T. + * typename T must be plain-old-data and contain an unsigned integral + * member T::identifier that uniquely identifies T with respect to + * other types used by the protocol being implemented. + * + * @param aPtr Pointer to receive the shared memory address. + * This value is set if and only if the function + * succeeded. + * @return NS_OK if and only if aPtr was successfully obtained. + * NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm or if + * type T does not match the type of the data + * stored in shared memory. + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. + */ + template <typename T> + nsresult GetReadPtr(const T*& aPtr) { + if (!mReadHeader) { + return NS_ERROR_NOT_INITIALIZED; + } + if (mReadHeader->mId != T::identifier || + sizeof(T) != mReadHeader->mPayloadLen) { + return NS_ERROR_ILLEGAL_VALUE; + } + aPtr = reinterpret_cast<const T*>(mReadHeader + 1); + return NS_OK; + } + + /** + * Fires the peer's event causing its request handler to execute. + * + * @return Should return NS_OK if the send was successful. + */ + virtual nsresult Send() = 0; + + protected: + /** + * MiniShm reserves some identifier codes for its own use. Any + * identifiers used by MiniShm protocol implementations must be + * greater than RESERVED_CODE_LAST. + */ + enum ReservedCodes { + RESERVED_CODE_INIT = 0, + RESERVED_CODE_INIT_COMPLETE = 1, + RESERVED_CODE_LAST = RESERVED_CODE_INIT_COMPLETE + }; + + struct MiniShmHeader { + unsigned int mId; + unsigned int mPayloadLen; + }; + + struct MiniShmInit { + enum identifier_t { identifier = RESERVED_CODE_INIT }; + HANDLE mParentEvent; + HANDLE mParentGuard; + HANDLE mChildEvent; + HANDLE mChildGuard; + }; + + struct MiniShmInitComplete { + enum identifier_t { identifier = RESERVED_CODE_INIT_COMPLETE }; + bool mSucceeded; + }; + + MiniShmBase() + : mObserver(nullptr), + mWriteHeader(nullptr), + mReadHeader(nullptr), + mPayloadMaxLen(0), + mGuard(nullptr), + mTimeout(INFINITE) {} + virtual ~MiniShmBase() {} + + virtual void OnEvent() { + if (mObserver) { + mObserver->OnMiniShmEvent(this); + } + } + + virtual void OnConnect() { + if (mObserver) { + mObserver->OnMiniShmConnect(this); + } + } + + nsresult SetView(LPVOID aView, const unsigned int aSize, bool aIsChild) { + if (!aView || aSize <= 2 * sizeof(MiniShmHeader)) { + return NS_ERROR_ILLEGAL_VALUE; + } + // Divide the region into halves for parent and child + if (aIsChild) { + mReadHeader = static_cast<MiniShmHeader*>(aView); + mWriteHeader = reinterpret_cast<MiniShmHeader*>( + static_cast<char*>(aView) + aSize / 2U); + } else { + mWriteHeader = static_cast<MiniShmHeader*>(aView); + mReadHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView) + + aSize / 2U); + } + mPayloadMaxLen = aSize / 2U - sizeof(MiniShmHeader); + return NS_OK; + } + + nsresult SetGuard(HANDLE aGuard, DWORD aTimeout) { + if (!aGuard || !aTimeout) { + return NS_ERROR_ILLEGAL_VALUE; + } + mGuard = aGuard; + mTimeout = aTimeout; + return NS_OK; + } + + inline void SetObserver(MiniShmObserver* aObserver) { mObserver = aObserver; } + + /** + * Obtains a writable pointer into shared memory of type T. This version + * differs from GetWritePtr in that it allows typename T to be one of + * the private data structures declared in MiniShmBase. + * + * @param aPtr Pointer to receive the shared memory address. + * This value is set if and only if the function + * succeeded. + * @return NS_OK if and only if aPtr was successfully obtained. + * NS_ERROR_ILLEGAL_VALUE if type T not an internal MiniShm struct. + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. + */ + template <typename T> + nsresult GetWritePtrInternal(T*& aPtr) { + if (!mWriteHeader) { + return NS_ERROR_NOT_INITIALIZED; + } + if (sizeof(T) > mPayloadMaxLen || + (int)T::identifier > (int)RESERVED_CODE_LAST) { + return NS_ERROR_ILLEGAL_VALUE; + } + mWriteHeader->mId = T::identifier; + mWriteHeader->mPayloadLen = sizeof(T); + aPtr = reinterpret_cast<T*>(mWriteHeader + 1); + return NS_OK; + } + + static VOID CALLBACK SOnEvent(PVOID aContext, BOOLEAN aIsTimer) { + MiniShmBase* object = static_cast<MiniShmBase*>(aContext); + object->OnEvent(); + } + + private: + MiniShmObserver* mObserver; + MiniShmHeader* mWriteHeader; + MiniShmHeader* mReadHeader; + unsigned int mPayloadMaxLen; + HANDLE mGuard; + DWORD mTimeout; + + DISALLOW_COPY_AND_ASSIGN(MiniShmBase); +}; + +} // namespace plugins +} // namespace mozilla + +#endif // mozilla_plugins_MiniShmBase_h |