1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/ipc/hangui/MiniShmBase.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,334 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_plugins_MiniShmBase_h 1.11 +#define mozilla_plugins_MiniShmBase_h 1.12 + 1.13 +#include "base/basictypes.h" 1.14 + 1.15 +#include "nsDebug.h" 1.16 + 1.17 +#include <windows.h> 1.18 + 1.19 +namespace mozilla { 1.20 +namespace plugins { 1.21 + 1.22 +/** 1.23 + * This class is used to provide RAII semantics for mapped views. 1.24 + * @see ScopedHandle 1.25 + */ 1.26 +class ScopedMappedFileView 1.27 +{ 1.28 +public: 1.29 + explicit 1.30 + ScopedMappedFileView(LPVOID aView) 1.31 + : mView(aView) 1.32 + { 1.33 + } 1.34 + 1.35 + ~ScopedMappedFileView() 1.36 + { 1.37 + Close(); 1.38 + } 1.39 + 1.40 + void 1.41 + Close() 1.42 + { 1.43 + if (mView) { 1.44 + ::UnmapViewOfFile(mView); 1.45 + mView = nullptr; 1.46 + } 1.47 + } 1.48 + 1.49 + void 1.50 + Set(LPVOID aView) 1.51 + { 1.52 + Close(); 1.53 + mView = aView; 1.54 + } 1.55 + 1.56 + LPVOID 1.57 + Get() const 1.58 + { 1.59 + return mView; 1.60 + } 1.61 + 1.62 + LPVOID 1.63 + Take() 1.64 + { 1.65 + LPVOID result = mView; 1.66 + mView = nullptr; 1.67 + return result; 1.68 + } 1.69 + 1.70 + operator LPVOID() 1.71 + { 1.72 + return mView; 1.73 + } 1.74 + 1.75 + bool 1.76 + IsValid() const 1.77 + { 1.78 + return (mView); 1.79 + } 1.80 + 1.81 +private: 1.82 + DISALLOW_COPY_AND_ASSIGN(ScopedMappedFileView); 1.83 + 1.84 + LPVOID mView; 1.85 +}; 1.86 + 1.87 +class MiniShmBase; 1.88 + 1.89 +class MiniShmObserver 1.90 +{ 1.91 +public: 1.92 + /** 1.93 + * This function is called whenever there is a new shared memory request. 1.94 + * @param aMiniShmObj MiniShmBase object that may be used to read and 1.95 + * write from shared memory. 1.96 + */ 1.97 + virtual void OnMiniShmEvent(MiniShmBase *aMiniShmObj) = 0; 1.98 + /** 1.99 + * This function is called once when a MiniShmParent and a MiniShmChild 1.100 + * object have successfully negotiated a connection. 1.101 + * 1.102 + * @param aMiniShmObj MiniShmBase object that may be used to read and 1.103 + * write from shared memory. 1.104 + */ 1.105 + virtual void OnMiniShmConnect(MiniShmBase *aMiniShmObj) { } 1.106 +}; 1.107 + 1.108 +/** 1.109 + * Base class for MiniShm connections. This class defines the common 1.110 + * interfaces and code between parent and child. 1.111 + */ 1.112 +class MiniShmBase 1.113 +{ 1.114 +public: 1.115 + /** 1.116 + * Obtains a writable pointer into shared memory of type T. 1.117 + * typename T must be plain-old-data and contain an unsigned integral 1.118 + * member T::identifier that uniquely identifies T with respect to 1.119 + * other types used by the protocol being implemented. 1.120 + * 1.121 + * @param aPtr Pointer to receive the shared memory address. 1.122 + * This value is set if and only if the function 1.123 + * succeeded. 1.124 + * @return NS_OK if and only if aPtr was successfully obtained. 1.125 + * NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm. 1.126 + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. 1.127 + * NS_ERROR_NOT_AVAILABLE if the memory is not safe to write. 1.128 + */ 1.129 + template<typename T> nsresult 1.130 + GetWritePtr(T*& aPtr) 1.131 + { 1.132 + if (!mWriteHeader || !mGuard) { 1.133 + return NS_ERROR_NOT_INITIALIZED; 1.134 + } 1.135 + if (sizeof(T) > mPayloadMaxLen || 1.136 + T::identifier <= RESERVED_CODE_LAST) { 1.137 + return NS_ERROR_ILLEGAL_VALUE; 1.138 + } 1.139 + if (::WaitForSingleObject(mGuard, mTimeout) != WAIT_OBJECT_0) { 1.140 + return NS_ERROR_NOT_AVAILABLE; 1.141 + } 1.142 + mWriteHeader->mId = T::identifier; 1.143 + mWriteHeader->mPayloadLen = sizeof(T); 1.144 + aPtr = reinterpret_cast<T*>(mWriteHeader + 1); 1.145 + return NS_OK; 1.146 + } 1.147 + 1.148 + /** 1.149 + * Obtains a readable pointer into shared memory of type T. 1.150 + * typename T must be plain-old-data and contain an unsigned integral 1.151 + * member T::identifier that uniquely identifies T with respect to 1.152 + * other types used by the protocol being implemented. 1.153 + * 1.154 + * @param aPtr Pointer to receive the shared memory address. 1.155 + * This value is set if and only if the function 1.156 + * succeeded. 1.157 + * @return NS_OK if and only if aPtr was successfully obtained. 1.158 + * NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm or if 1.159 + * type T does not match the type of the data 1.160 + * stored in shared memory. 1.161 + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. 1.162 + */ 1.163 + template<typename T> nsresult 1.164 + GetReadPtr(const T*& aPtr) 1.165 + { 1.166 + if (!mReadHeader) { 1.167 + return NS_ERROR_NOT_INITIALIZED; 1.168 + } 1.169 + if (mReadHeader->mId != T::identifier || 1.170 + sizeof(T) != mReadHeader->mPayloadLen) { 1.171 + return NS_ERROR_ILLEGAL_VALUE; 1.172 + } 1.173 + aPtr = reinterpret_cast<const T*>(mReadHeader + 1); 1.174 + return NS_OK; 1.175 + } 1.176 + 1.177 + /** 1.178 + * Fires the peer's event causing its request handler to execute. 1.179 + * 1.180 + * @return Should return NS_OK if the send was successful. 1.181 + */ 1.182 + virtual nsresult 1.183 + Send() = 0; 1.184 + 1.185 +protected: 1.186 + /** 1.187 + * MiniShm reserves some identifier codes for its own use. Any 1.188 + * identifiers used by MiniShm protocol implementations must be 1.189 + * greater than RESERVED_CODE_LAST. 1.190 + */ 1.191 + enum ReservedCodes 1.192 + { 1.193 + RESERVED_CODE_INIT = 0, 1.194 + RESERVED_CODE_INIT_COMPLETE = 1, 1.195 + RESERVED_CODE_LAST = RESERVED_CODE_INIT_COMPLETE 1.196 + }; 1.197 + 1.198 + struct MiniShmHeader 1.199 + { 1.200 + unsigned int mId; 1.201 + unsigned int mPayloadLen; 1.202 + }; 1.203 + 1.204 + struct MiniShmInit 1.205 + { 1.206 + enum identifier_t 1.207 + { 1.208 + identifier = RESERVED_CODE_INIT 1.209 + }; 1.210 + HANDLE mParentEvent; 1.211 + HANDLE mParentGuard; 1.212 + HANDLE mChildEvent; 1.213 + HANDLE mChildGuard; 1.214 + }; 1.215 + 1.216 + struct MiniShmInitComplete 1.217 + { 1.218 + enum identifier_t 1.219 + { 1.220 + identifier = RESERVED_CODE_INIT_COMPLETE 1.221 + }; 1.222 + bool mSucceeded; 1.223 + }; 1.224 + 1.225 + MiniShmBase() 1.226 + : mObserver(nullptr), 1.227 + mWriteHeader(nullptr), 1.228 + mReadHeader(nullptr), 1.229 + mPayloadMaxLen(0), 1.230 + mGuard(nullptr), 1.231 + mTimeout(INFINITE) 1.232 + { 1.233 + } 1.234 + virtual ~MiniShmBase() 1.235 + { } 1.236 + 1.237 + virtual void 1.238 + OnEvent() 1.239 + { 1.240 + if (mObserver) { 1.241 + mObserver->OnMiniShmEvent(this); 1.242 + } 1.243 + } 1.244 + 1.245 + virtual void 1.246 + OnConnect() 1.247 + { 1.248 + if (mObserver) { 1.249 + mObserver->OnMiniShmConnect(this); 1.250 + } 1.251 + } 1.252 + 1.253 + nsresult 1.254 + SetView(LPVOID aView, const unsigned int aSize, bool aIsChild) 1.255 + { 1.256 + if (!aView || aSize <= 2 * sizeof(MiniShmHeader)) { 1.257 + return NS_ERROR_ILLEGAL_VALUE; 1.258 + } 1.259 + // Divide the region into halves for parent and child 1.260 + if (aIsChild) { 1.261 + mReadHeader = static_cast<MiniShmHeader*>(aView); 1.262 + mWriteHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView) 1.263 + + aSize / 2U); 1.264 + } else { 1.265 + mWriteHeader = static_cast<MiniShmHeader*>(aView); 1.266 + mReadHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView) 1.267 + + aSize / 2U); 1.268 + } 1.269 + mPayloadMaxLen = aSize / 2U - sizeof(MiniShmHeader); 1.270 + return NS_OK; 1.271 + } 1.272 + 1.273 + nsresult 1.274 + SetGuard(HANDLE aGuard, DWORD aTimeout) 1.275 + { 1.276 + if (!aGuard || !aTimeout) { 1.277 + return NS_ERROR_ILLEGAL_VALUE; 1.278 + } 1.279 + mGuard = aGuard; 1.280 + mTimeout = aTimeout; 1.281 + return NS_OK; 1.282 + } 1.283 + 1.284 + inline void 1.285 + SetObserver(MiniShmObserver *aObserver) { mObserver = aObserver; } 1.286 + 1.287 + /** 1.288 + * Obtains a writable pointer into shared memory of type T. This version 1.289 + * differs from GetWritePtr in that it allows typename T to be one of 1.290 + * the private data structures declared in MiniShmBase. 1.291 + * 1.292 + * @param aPtr Pointer to receive the shared memory address. 1.293 + * This value is set if and only if the function 1.294 + * succeeded. 1.295 + * @return NS_OK if and only if aPtr was successfully obtained. 1.296 + * NS_ERROR_ILLEGAL_VALUE if type T not an internal MiniShm struct. 1.297 + * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. 1.298 + */ 1.299 + template<typename T> nsresult 1.300 + GetWritePtrInternal(T*& aPtr) 1.301 + { 1.302 + if (!mWriteHeader) { 1.303 + return NS_ERROR_NOT_INITIALIZED; 1.304 + } 1.305 + if (sizeof(T) > mPayloadMaxLen || 1.306 + T::identifier > RESERVED_CODE_LAST) { 1.307 + return NS_ERROR_ILLEGAL_VALUE; 1.308 + } 1.309 + mWriteHeader->mId = T::identifier; 1.310 + mWriteHeader->mPayloadLen = sizeof(T); 1.311 + aPtr = reinterpret_cast<T*>(mWriteHeader + 1); 1.312 + return NS_OK; 1.313 + } 1.314 + 1.315 + static VOID CALLBACK 1.316 + SOnEvent(PVOID aContext, BOOLEAN aIsTimer) 1.317 + { 1.318 + MiniShmBase* object = static_cast<MiniShmBase*>(aContext); 1.319 + object->OnEvent(); 1.320 + } 1.321 + 1.322 +private: 1.323 + MiniShmObserver* mObserver; 1.324 + MiniShmHeader* mWriteHeader; 1.325 + MiniShmHeader* mReadHeader; 1.326 + unsigned int mPayloadMaxLen; 1.327 + HANDLE mGuard; 1.328 + DWORD mTimeout; 1.329 + 1.330 + DISALLOW_COPY_AND_ASSIGN(MiniShmBase); 1.331 +}; 1.332 + 1.333 +} // namespace plugins 1.334 +} // namespace mozilla 1.335 + 1.336 +#endif // mozilla_plugins_MiniShmBase_h 1.337 +