ipc/glue/FileDescriptor.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/glue/FileDescriptor.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,158 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#ifndef mozilla_ipc_FileDescriptor_h
     1.9 +#define mozilla_ipc_FileDescriptor_h
    1.10 +
    1.11 +#include "base/basictypes.h"
    1.12 +#include "base/process.h"
    1.13 +#include "mozilla/DebugOnly.h"
    1.14 +#include "nscore.h"
    1.15 +
    1.16 +#ifdef XP_WIN
    1.17 +// Need the HANDLE typedef.
    1.18 +#include <winnt.h>
    1.19 +#else
    1.20 +#include "base/file_descriptor_posix.h"
    1.21 +#endif
    1.22 +
    1.23 +namespace mozilla {
    1.24 +namespace ipc {
    1.25 +
    1.26 +// This class is used by IPDL to share file descriptors across processes. When
    1.27 +// sending a FileDescriptor IPDL will first duplicate a platform-specific file
    1.28 +// handle type ('PlatformHandleType') into a handle that is valid in the other
    1.29 +// process. Then IPDL will convert the duplicated handle into a type suitable
    1.30 +// for pickling ('PickleType') and then send that through the IPC pipe. In the
    1.31 +// receiving process the pickled data is converted into a platform-specific file
    1.32 +// handle and then returned to the receiver.
    1.33 +//
    1.34 +// To use this class add 'FileDescriptor' as an argument in the IPDL protocol
    1.35 +// and then pass a file descriptor from C++ to the Call/Send method. The
    1.36 +// Answer/Recv method will receive a FileDescriptor& on which PlatformHandle()
    1.37 +// can be called to return the platform file handle.
    1.38 +class FileDescriptor
    1.39 +{
    1.40 +public:
    1.41 +  typedef base::ProcessHandle ProcessHandle;
    1.42 +
    1.43 +#ifdef XP_WIN
    1.44 +  typedef HANDLE PlatformHandleType;
    1.45 +  typedef HANDLE PickleType;
    1.46 +#else
    1.47 +  typedef int PlatformHandleType;
    1.48 +  typedef base::FileDescriptor PickleType;
    1.49 +#endif
    1.50 +
    1.51 +  // This should only ever be created by IPDL.
    1.52 +  struct IPDLPrivate
    1.53 +  {};
    1.54 +
    1.55 +  FileDescriptor();
    1.56 +
    1.57 +  FileDescriptor(const FileDescriptor& aOther)
    1.58 +    : mHandleCreatedByOtherProcess(false),
    1.59 +      mHandleCreatedByOtherProcessWasUsed(false)
    1.60 +  {
    1.61 +    // Don't use operator= here because that will call
    1.62 +    // CloseCurrentProcessHandle() on this (uninitialized) object.
    1.63 +    Assign(aOther);
    1.64 +  }
    1.65 +
    1.66 +  FileDescriptor(PlatformHandleType aHandle);
    1.67 +
    1.68 +  FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
    1.69 +#ifdef XP_WIN
    1.70 +  : mHandle(aPickle)
    1.71 +#else
    1.72 +  : mHandle(aPickle.fd)
    1.73 +#endif
    1.74 +  , mHandleCreatedByOtherProcess(true)
    1.75 +  , mHandleCreatedByOtherProcessWasUsed(false)
    1.76 +  { }
    1.77 +
    1.78 +  ~FileDescriptor()
    1.79 +  {
    1.80 +    CloseCurrentProcessHandle();
    1.81 +  }
    1.82 +
    1.83 +  FileDescriptor&
    1.84 +  operator=(const FileDescriptor& aOther)
    1.85 +  {
    1.86 +    CloseCurrentProcessHandle();
    1.87 +    Assign(aOther);
    1.88 +    return *this;
    1.89 +  }
    1.90 +
    1.91 +  // Performs platform-specific actions to duplicate mHandle in the other
    1.92 +  // process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
    1.93 +  // pickled value that can be passed to the other process via IPC.
    1.94 +  PickleType
    1.95 +  ShareTo(const IPDLPrivate&, ProcessHandle aOtherProcess) const;
    1.96 +
    1.97 +  // Tests mHandle against a well-known invalid platform-specific file handle
    1.98 +  // (e.g. -1 on POSIX, INVALID_HANDLE_VALUE on Windows).
    1.99 +  bool
   1.100 +  IsValid() const
   1.101 +  {
   1.102 +    return IsValid(mHandle);
   1.103 +  }
   1.104 +
   1.105 +  PlatformHandleType
   1.106 +  PlatformHandle() const
   1.107 +  {
   1.108 +    if (mHandleCreatedByOtherProcess) {
   1.109 +      mHandleCreatedByOtherProcessWasUsed = true;
   1.110 +    }
   1.111 +    return mHandle;
   1.112 +  }
   1.113 +
   1.114 +  bool
   1.115 +  operator==(const FileDescriptor& aOther) const
   1.116 +  {
   1.117 +    return mHandle == aOther.mHandle;
   1.118 +  }
   1.119 +
   1.120 +private:
   1.121 +  void
   1.122 +  Assign(const FileDescriptor& aOther)
   1.123 +  {
   1.124 +    if (aOther.mHandleCreatedByOtherProcess) {
   1.125 +      mHandleCreatedByOtherProcess = true;
   1.126 +      mHandleCreatedByOtherProcessWasUsed =
   1.127 +        aOther.mHandleCreatedByOtherProcessWasUsed;
   1.128 +      mHandle = aOther.PlatformHandle();
   1.129 +    } else {
   1.130 +      DuplicateInCurrentProcess(aOther.PlatformHandle());
   1.131 +      mHandleCreatedByOtherProcess = false;
   1.132 +      mHandleCreatedByOtherProcessWasUsed = false;
   1.133 +    }
   1.134 +  }
   1.135 +
   1.136 +  static bool
   1.137 +  IsValid(PlatformHandleType aHandle);
   1.138 +
   1.139 +  void
   1.140 +  DuplicateInCurrentProcess(PlatformHandleType aHandle);
   1.141 +
   1.142 +  void
   1.143 +  CloseCurrentProcessHandle();
   1.144 +
   1.145 +  PlatformHandleType mHandle;
   1.146 +
   1.147 +  // If this is true then this instance is created by IPDL to ferry a handle to
   1.148 +  // its eventual consumer and we never close the handle. If this is false then
   1.149 +  // we are a RAII wrapper around the handle and we close the handle on
   1.150 +  // destruction.
   1.151 +  bool mHandleCreatedByOtherProcess;
   1.152 +
   1.153 +  // This is to ensure that we don't leak the handle (which is only possible
   1.154 +  // when we're in the receiving process).
   1.155 +  mutable DebugOnly<bool> mHandleCreatedByOtherProcessWasUsed;
   1.156 +};
   1.157 +
   1.158 +} // namespace ipc
   1.159 +} // namespace mozilla
   1.160 +
   1.161 +#endif // mozilla_ipc_FileDescriptor_h

mercurial