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