1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef IPC_MACH_PORT_MAC_H_ 6 #define IPC_MACH_PORT_MAC_H_ 7 8 #include <mach/mach.h> 9 10 #include "base/pickle.h" 11 #include "ipc/ipc_message_support_export.h" 12 #include "ipc/ipc_param_traits.h" 13 14 namespace IPC { 15 16 // MachPortMac is a wrapper around an OSX Mach port that can be transported 17 // across Chrome IPC channels that support attachment brokering. The send right 18 // to the Mach port will be duplicated into the destination process by the 19 // attachment broker. If needed, attachment brokering can be trivially extended 20 // to support duplication of other types of rights. 21 class IPC_MESSAGE_SUPPORT_EXPORT MachPortMac { 22 public: MachPortMac()23 MachPortMac() : mach_port_(MACH_PORT_NULL) {} 24 MachPortMac(mach_port_t mach_port)25 explicit MachPortMac(mach_port_t mach_port) : mach_port_(mach_port) {} 26 27 MachPortMac(const MachPortMac&) = delete; 28 MachPortMac& operator=(const MachPortMac&) = delete; 29 get_mach_port()30 mach_port_t get_mach_port() const { return mach_port_; } 31 32 // This method should only be used by ipc/ translation code. set_mach_port(mach_port_t mach_port)33 void set_mach_port(mach_port_t mach_port) { mach_port_ = mach_port; } 34 35 private: 36 // The ownership semantics of |mach_port_| cannot be easily expressed with a 37 // C++ scoped object. This is partly due to the mechanism by which Mach ports 38 // are brokered, and partly due to the architecture of Chrome IPC. 39 // 40 // The broker for Mach ports may live in a different process than the sender 41 // of the original Chrome IPC. In this case, it is signalled asynchronously, 42 // and ownership of the Mach port passes from the sender process into the 43 // broker process. 44 // 45 // Chrome IPC is written with the assumption that translation is a stateless 46 // process. There is no good mechanism to convey the semantics of ownership 47 // transfer from the Chrome IPC stack into the client code that receives the 48 // translated message. As a result, Chrome IPC code assumes that every message 49 // has a handler, and that the handler will take ownership of the Mach port. 50 // Note that the same holds true for POSIX fds and Windows HANDLEs. 51 // 52 // When used by client code in the sender process, this class is just a 53 // wrapper. The client code calls Send(new Message(MachPortMac(mach_port))) 54 // and continues on its merry way. Behind the scenes, a MachPortAttachmentMac 55 // takes ownership of the Mach port. When the attachment broker sends the name 56 // of the Mach port to the broker process, it also releases 57 // MachPortAttachmentMac's reference to the Mach port, as ownership has 58 // effectively been transferred to the broker process. 59 // 60 // The broker process receives the name, duplicates the Mach port into the 61 // destination process, and then decrements the ref count in the original 62 // process. 63 // 64 // In the destination process, the attachment broker is responsible for 65 // coupling the Mach port (inserted by the broker process) with Chrome IPC in 66 // the form of a MachPortAttachmentMac. Due to the Chrome IPC translation 67 // semantics discussed above, this MachPortAttachmentMac does not take 68 // ownership of the Mach port, and assumes that the client code which receives 69 // the callback will take ownership of the Mach port. 70 mach_port_t mach_port_; 71 }; 72 73 template <> 74 struct IPC_MESSAGE_SUPPORT_EXPORT ParamTraits<MachPortMac> { 75 typedef MachPortMac param_type; 76 static void Write(base::Pickle* m, const param_type& p); 77 static bool Read(const base::Pickle* m, 78 base::PickleIterator* iter, 79 param_type* p); 80 static void Log(const param_type& p, std::string* l); 81 }; 82 83 } // namespace IPC 84 85 #endif // IPC_MACH_PORT_MAC_H_ 86