ipc/glue/FileDescriptor.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 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef mozilla_ipc_FileDescriptor_h
     6 #define mozilla_ipc_FileDescriptor_h
     8 #include "base/basictypes.h"
     9 #include "base/process.h"
    10 #include "mozilla/DebugOnly.h"
    11 #include "nscore.h"
    13 #ifdef XP_WIN
    14 // Need the HANDLE typedef.
    15 #include <winnt.h>
    16 #else
    17 #include "base/file_descriptor_posix.h"
    18 #endif
    20 namespace mozilla {
    21 namespace ipc {
    23 // This class is used by IPDL to share file descriptors across processes. When
    24 // sending a FileDescriptor IPDL will first duplicate a platform-specific file
    25 // handle type ('PlatformHandleType') into a handle that is valid in the other
    26 // process. Then IPDL will convert the duplicated handle into a type suitable
    27 // for pickling ('PickleType') and then send that through the IPC pipe. In the
    28 // receiving process the pickled data is converted into a platform-specific file
    29 // handle and then returned to the receiver.
    30 //
    31 // To use this class add 'FileDescriptor' as an argument in the IPDL protocol
    32 // and then pass a file descriptor from C++ to the Call/Send method. The
    33 // Answer/Recv method will receive a FileDescriptor& on which PlatformHandle()
    34 // can be called to return the platform file handle.
    35 class FileDescriptor
    36 {
    37 public:
    38   typedef base::ProcessHandle ProcessHandle;
    40 #ifdef XP_WIN
    41   typedef HANDLE PlatformHandleType;
    42   typedef HANDLE PickleType;
    43 #else
    44   typedef int PlatformHandleType;
    45   typedef base::FileDescriptor PickleType;
    46 #endif
    48   // This should only ever be created by IPDL.
    49   struct IPDLPrivate
    50   {};
    52   FileDescriptor();
    54   FileDescriptor(const FileDescriptor& aOther)
    55     : mHandleCreatedByOtherProcess(false),
    56       mHandleCreatedByOtherProcessWasUsed(false)
    57   {
    58     // Don't use operator= here because that will call
    59     // CloseCurrentProcessHandle() on this (uninitialized) object.
    60     Assign(aOther);
    61   }
    63   FileDescriptor(PlatformHandleType aHandle);
    65   FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
    66 #ifdef XP_WIN
    67   : mHandle(aPickle)
    68 #else
    69   : mHandle(aPickle.fd)
    70 #endif
    71   , mHandleCreatedByOtherProcess(true)
    72   , mHandleCreatedByOtherProcessWasUsed(false)
    73   { }
    75   ~FileDescriptor()
    76   {
    77     CloseCurrentProcessHandle();
    78   }
    80   FileDescriptor&
    81   operator=(const FileDescriptor& aOther)
    82   {
    83     CloseCurrentProcessHandle();
    84     Assign(aOther);
    85     return *this;
    86   }
    88   // Performs platform-specific actions to duplicate mHandle in the other
    89   // process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
    90   // pickled value that can be passed to the other process via IPC.
    91   PickleType
    92   ShareTo(const IPDLPrivate&, ProcessHandle aOtherProcess) const;
    94   // Tests mHandle against a well-known invalid platform-specific file handle
    95   // (e.g. -1 on POSIX, INVALID_HANDLE_VALUE on Windows).
    96   bool
    97   IsValid() const
    98   {
    99     return IsValid(mHandle);
   100   }
   102   PlatformHandleType
   103   PlatformHandle() const
   104   {
   105     if (mHandleCreatedByOtherProcess) {
   106       mHandleCreatedByOtherProcessWasUsed = true;
   107     }
   108     return mHandle;
   109   }
   111   bool
   112   operator==(const FileDescriptor& aOther) const
   113   {
   114     return mHandle == aOther.mHandle;
   115   }
   117 private:
   118   void
   119   Assign(const FileDescriptor& aOther)
   120   {
   121     if (aOther.mHandleCreatedByOtherProcess) {
   122       mHandleCreatedByOtherProcess = true;
   123       mHandleCreatedByOtherProcessWasUsed =
   124         aOther.mHandleCreatedByOtherProcessWasUsed;
   125       mHandle = aOther.PlatformHandle();
   126     } else {
   127       DuplicateInCurrentProcess(aOther.PlatformHandle());
   128       mHandleCreatedByOtherProcess = false;
   129       mHandleCreatedByOtherProcessWasUsed = false;
   130     }
   131   }
   133   static bool
   134   IsValid(PlatformHandleType aHandle);
   136   void
   137   DuplicateInCurrentProcess(PlatformHandleType aHandle);
   139   void
   140   CloseCurrentProcessHandle();
   142   PlatformHandleType mHandle;
   144   // If this is true then this instance is created by IPDL to ferry a handle to
   145   // its eventual consumer and we never close the handle. If this is false then
   146   // we are a RAII wrapper around the handle and we close the handle on
   147   // destruction.
   148   bool mHandleCreatedByOtherProcess;
   150   // This is to ensure that we don't leak the handle (which is only possible
   151   // when we're in the receiving process).
   152   mutable DebugOnly<bool> mHandleCreatedByOtherProcessWasUsed;
   153 };
   155 } // namespace ipc
   156 } // namespace mozilla
   158 #endif // mozilla_ipc_FileDescriptor_h

mercurial