dom/plugins/ipc/hangui/MiniShmBase.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef mozilla_plugins_MiniShmBase_h
     8 #define mozilla_plugins_MiniShmBase_h
    10 #include "base/basictypes.h"
    12 #include "nsDebug.h"
    14 #include <windows.h>
    16 namespace mozilla {
    17 namespace plugins {
    19 /**
    20  * This class is used to provide RAII semantics for mapped views.
    21  * @see ScopedHandle
    22  */
    23 class ScopedMappedFileView
    24 {
    25 public:
    26   explicit
    27   ScopedMappedFileView(LPVOID aView)
    28     : mView(aView)
    29   {
    30   }
    32   ~ScopedMappedFileView()
    33   {
    34     Close();
    35   }
    37   void
    38   Close()
    39   {
    40     if (mView) {
    41       ::UnmapViewOfFile(mView);
    42       mView = nullptr;
    43     }
    44   }
    46   void
    47   Set(LPVOID aView)
    48   {
    49     Close();
    50     mView = aView;
    51   }
    53   LPVOID
    54   Get() const
    55   {
    56     return mView;
    57   }
    59   LPVOID
    60   Take()
    61   {
    62     LPVOID result = mView;
    63     mView = nullptr;
    64     return result;
    65   }
    67   operator LPVOID()
    68   {
    69     return mView;
    70   }
    72   bool
    73   IsValid() const
    74   {
    75     return (mView);
    76   }
    78 private:
    79   DISALLOW_COPY_AND_ASSIGN(ScopedMappedFileView);
    81   LPVOID mView;
    82 };
    84 class MiniShmBase;
    86 class MiniShmObserver
    87 {
    88 public:
    89   /**
    90    * This function is called whenever there is a new shared memory request.
    91    * @param aMiniShmObj MiniShmBase object that may be used to read and 
    92    *                    write from shared memory.
    93    */
    94   virtual void OnMiniShmEvent(MiniShmBase *aMiniShmObj) = 0;
    95   /**
    96    * This function is called once when a MiniShmParent and a MiniShmChild
    97    * object have successfully negotiated a connection.
    98    *
    99    * @param aMiniShmObj MiniShmBase object that may be used to read and 
   100    *                    write from shared memory.
   101    */
   102   virtual void OnMiniShmConnect(MiniShmBase *aMiniShmObj) { }
   103 };
   105 /**
   106  * Base class for MiniShm connections. This class defines the common 
   107  * interfaces and code between parent and child.
   108  */
   109 class MiniShmBase
   110 {
   111 public:
   112   /**
   113    * Obtains a writable pointer into shared memory of type T.
   114    * typename T must be plain-old-data and contain an unsigned integral 
   115    * member T::identifier that uniquely identifies T with respect to 
   116    * other types used by the protocol being implemented.
   117    *
   118    * @param aPtr Pointer to receive the shared memory address.
   119    *             This value is set if and only if the function 
   120    *             succeeded.
   121    * @return NS_OK if and only if aPtr was successfully obtained.
   122    *         NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm.
   123    *         NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
   124    *         NS_ERROR_NOT_AVAILABLE if the memory is not safe to write.
   125    */
   126   template<typename T> nsresult
   127   GetWritePtr(T*& aPtr)
   128   {
   129     if (!mWriteHeader || !mGuard) {
   130       return NS_ERROR_NOT_INITIALIZED;
   131     }
   132     if (sizeof(T) > mPayloadMaxLen ||
   133         T::identifier <= RESERVED_CODE_LAST) {
   134       return NS_ERROR_ILLEGAL_VALUE;
   135     }
   136     if (::WaitForSingleObject(mGuard, mTimeout) != WAIT_OBJECT_0) {
   137       return NS_ERROR_NOT_AVAILABLE;
   138     }
   139     mWriteHeader->mId = T::identifier;
   140     mWriteHeader->mPayloadLen = sizeof(T);
   141     aPtr = reinterpret_cast<T*>(mWriteHeader + 1);
   142     return NS_OK;
   143   }
   145   /**
   146    * Obtains a readable pointer into shared memory of type T.
   147    * typename T must be plain-old-data and contain an unsigned integral 
   148    * member T::identifier that uniquely identifies T with respect to 
   149    * other types used by the protocol being implemented.
   150    *
   151    * @param aPtr Pointer to receive the shared memory address.
   152    *             This value is set if and only if the function 
   153    *             succeeded.
   154    * @return NS_OK if and only if aPtr was successfully obtained.
   155    *         NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm or if
   156    *                                type T does not match the type of the data
   157    *                                stored in shared memory.
   158    *         NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
   159    */
   160   template<typename T> nsresult
   161   GetReadPtr(const T*& aPtr)
   162   {
   163     if (!mReadHeader) {
   164       return NS_ERROR_NOT_INITIALIZED;
   165     }
   166     if (mReadHeader->mId != T::identifier ||
   167         sizeof(T) != mReadHeader->mPayloadLen) {
   168       return NS_ERROR_ILLEGAL_VALUE;
   169     }
   170     aPtr = reinterpret_cast<const T*>(mReadHeader + 1);
   171     return NS_OK;
   172   }
   174   /**
   175    * Fires the peer's event causing its request handler to execute.
   176    *
   177    * @return Should return NS_OK if the send was successful.
   178    */
   179   virtual nsresult
   180   Send() = 0;
   182 protected:
   183   /**
   184    * MiniShm reserves some identifier codes for its own use. Any 
   185    * identifiers used by MiniShm protocol implementations must be 
   186    * greater than RESERVED_CODE_LAST.
   187    */
   188   enum ReservedCodes
   189   {
   190     RESERVED_CODE_INIT = 0,
   191     RESERVED_CODE_INIT_COMPLETE = 1,
   192     RESERVED_CODE_LAST = RESERVED_CODE_INIT_COMPLETE
   193   };
   195   struct MiniShmHeader
   196   {
   197     unsigned int  mId;
   198     unsigned int  mPayloadLen;
   199   };
   201   struct MiniShmInit
   202   {
   203     enum identifier_t
   204     {
   205       identifier = RESERVED_CODE_INIT
   206     };
   207     HANDLE    mParentEvent;
   208     HANDLE    mParentGuard;
   209     HANDLE    mChildEvent;
   210     HANDLE    mChildGuard;
   211   };
   213   struct MiniShmInitComplete
   214   {
   215     enum identifier_t
   216     {
   217       identifier = RESERVED_CODE_INIT_COMPLETE
   218     };
   219     bool      mSucceeded;
   220   };
   222   MiniShmBase()
   223     : mObserver(nullptr),
   224       mWriteHeader(nullptr),
   225       mReadHeader(nullptr),
   226       mPayloadMaxLen(0),
   227       mGuard(nullptr),
   228       mTimeout(INFINITE)
   229   {
   230   }
   231   virtual ~MiniShmBase()
   232   { }
   234   virtual void
   235   OnEvent()
   236   {
   237     if (mObserver) {
   238       mObserver->OnMiniShmEvent(this);
   239     }
   240   }
   242   virtual void
   243   OnConnect()
   244   {
   245     if (mObserver) {
   246       mObserver->OnMiniShmConnect(this);
   247     }
   248   }
   250   nsresult
   251   SetView(LPVOID aView, const unsigned int aSize, bool aIsChild)
   252   {
   253     if (!aView || aSize <= 2 * sizeof(MiniShmHeader)) {
   254       return NS_ERROR_ILLEGAL_VALUE;
   255     }
   256     // Divide the region into halves for parent and child
   257     if (aIsChild) {
   258       mReadHeader = static_cast<MiniShmHeader*>(aView);
   259       mWriteHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView)
   260                                                       + aSize / 2U);
   261     } else {
   262       mWriteHeader = static_cast<MiniShmHeader*>(aView);
   263       mReadHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView)
   264                                                      + aSize / 2U);
   265     }
   266     mPayloadMaxLen = aSize / 2U - sizeof(MiniShmHeader);
   267     return NS_OK;
   268   }
   270   nsresult
   271   SetGuard(HANDLE aGuard, DWORD aTimeout)
   272   {
   273     if (!aGuard || !aTimeout) {
   274       return NS_ERROR_ILLEGAL_VALUE;
   275     }
   276     mGuard = aGuard;
   277     mTimeout = aTimeout;
   278     return NS_OK;
   279   }
   281   inline void
   282   SetObserver(MiniShmObserver *aObserver) { mObserver = aObserver; }
   284   /**
   285    * Obtains a writable pointer into shared memory of type T. This version 
   286    * differs from GetWritePtr in that it allows typename T to be one of 
   287    * the private data structures declared in MiniShmBase.
   288    *
   289    * @param aPtr Pointer to receive the shared memory address.
   290    *             This value is set if and only if the function 
   291    *             succeeded.
   292    * @return NS_OK if and only if aPtr was successfully obtained.
   293    *         NS_ERROR_ILLEGAL_VALUE if type T not an internal MiniShm struct.
   294    *         NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
   295    */
   296   template<typename T> nsresult
   297   GetWritePtrInternal(T*& aPtr)
   298   {
   299     if (!mWriteHeader) {
   300       return NS_ERROR_NOT_INITIALIZED;
   301     }
   302     if (sizeof(T) > mPayloadMaxLen ||
   303         T::identifier > RESERVED_CODE_LAST) {
   304       return NS_ERROR_ILLEGAL_VALUE;
   305     }
   306     mWriteHeader->mId = T::identifier;
   307     mWriteHeader->mPayloadLen = sizeof(T);
   308     aPtr = reinterpret_cast<T*>(mWriteHeader + 1);
   309     return NS_OK;
   310   }
   312   static VOID CALLBACK
   313   SOnEvent(PVOID aContext, BOOLEAN aIsTimer)
   314   {
   315     MiniShmBase* object = static_cast<MiniShmBase*>(aContext);
   316     object->OnEvent();
   317   }
   319 private:
   320   MiniShmObserver*  mObserver;
   321   MiniShmHeader*    mWriteHeader;
   322   MiniShmHeader*    mReadHeader;
   323   unsigned int      mPayloadMaxLen;
   324   HANDLE            mGuard;
   325   DWORD             mTimeout;
   327   DISALLOW_COPY_AND_ASSIGN(MiniShmBase);
   328 };
   330 } // namespace plugins
   331 } // namespace mozilla
   333 #endif // mozilla_plugins_MiniShmBase_h

mercurial