1 // Copyright 2018 The Chromium Authors. All rights reserved. 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 MOJO_PUBLIC_CPP_SYSTEM_INVITATION_H_ 6 #define MOJO_PUBLIC_CPP_SYSTEM_INVITATION_H_ 7 8 #include <cstdint> 9 #include <string> 10 11 #include "base/callback.h" 12 #include "base/component_export.h" 13 #include "base/macros.h" 14 #include "base/process/process_handle.h" 15 #include "base/strings/string_piece.h" 16 #include "mojo/public/c/system/invitation.h" 17 #include "mojo/public/cpp/platform/platform_channel_endpoint.h" 18 #include "mojo/public/cpp/platform/platform_channel_server_endpoint.h" 19 #include "mojo/public/cpp/system/handle.h" 20 #include "mojo/public/cpp/system/message_pipe.h" 21 #include "mojo/public/cpp/system/system_export.h" 22 23 namespace mojo { 24 25 // A callback which may be provided when sending an invitation to another 26 // process. In the event of any validation errors regarding messages from that 27 // process (reported via MojoNotifyBadMessage etc and related helpers), the 28 // callback will be invoked. 29 using ProcessErrorCallback = base::RepeatingCallback<void(const std::string&)>; 30 31 // A strongly-typed representation of a |MojoHandle| for an invitation. 32 class InvitationHandle : public Handle { 33 public: InvitationHandle()34 InvitationHandle() {} InvitationHandle(MojoHandle value)35 explicit InvitationHandle(MojoHandle value) : Handle(value) {} 36 37 // Copying and assignment allowed. 38 }; 39 40 static_assert(sizeof(InvitationHandle) == sizeof(Handle), 41 "Bad size for C++ InvitationHandle"); 42 43 using ScopedInvitationHandle = ScopedHandleBase<InvitationHandle>; 44 static_assert(sizeof(ScopedInvitationHandle) == sizeof(InvitationHandle), 45 "Bad size for C++ ScopedInvitationHandle"); 46 47 // An OutgoingInvitation is used to invite another process to join the calling 48 // process's IPC network. 49 // 50 // Typical use involves constructing a |PlatformChannel| and using one end to 51 // send the invitation (see |Send()| below) while passing the other to a child 52 // process. 53 // 54 // This may also be used with the server endpoint of a |NamedPlatformChannel|. 55 class MOJO_CPP_SYSTEM_EXPORT OutgoingInvitation { 56 public: 57 OutgoingInvitation(); 58 OutgoingInvitation(OutgoingInvitation&& other); 59 ~OutgoingInvitation(); 60 61 OutgoingInvitation& operator=(OutgoingInvitation&& other); 62 63 // Creates a new message pipe, attaching one end to this invitation and 64 // returning the other end to the caller. The invitee can extract the 65 // attached endpoint (see |IncomingInvitation|) thus establishing end-to-end 66 // Mojo communication. 67 // 68 // |name| is an arbitrary value that must be used by the invitee to extract 69 // the corresponding attached endpoint. 70 ScopedMessagePipeHandle AttachMessagePipe(base::StringPiece name); 71 72 // Same as above but allows use of an integer name for convenience. 73 ScopedMessagePipeHandle AttachMessagePipe(uint64_t name); 74 75 // Extracts an attached pipe. Note that this is not typically useful, but it 76 // is potentially necessary in cases where a caller wants to, e.g., abort 77 // launching another process and recover a pipe endpoint they had previously 78 // attached. 79 ScopedMessagePipeHandle ExtractMessagePipe(base::StringPiece name); 80 81 // Same as above but allows use of an integer name for convenience. 82 ScopedMessagePipeHandle ExtractMessagePipe(uint64_t name); 83 84 // Sends |invitation| to another process via |channel_endpoint|, which should 85 // correspond to the local endpoint taken from a |PlatformChannel|. 86 // 87 // |process_handle| is a handle to the destination process if known. If not 88 // provided, IPC may be limited on some platforms (namely Mac and Windows) due 89 // to an inability to transfer system handles across the boundary. 90 static void Send(OutgoingInvitation invitation, 91 base::ProcessHandle target_process, 92 PlatformChannelEndpoint channel_endpoint, 93 const ProcessErrorCallback& error_callback = {}); 94 95 // Similar to above, but sends |invitation| via |server_endpoint|, which 96 // should correspond to a |PlatformChannelServerEndpoint| taken from a 97 // |NamedPlatformChannel|. 98 static void Send(OutgoingInvitation invitation, 99 base::ProcessHandle target_process, 100 PlatformChannelServerEndpoint server_endpoint, 101 const ProcessErrorCallback& error_callback = {}); 102 103 // Similar to |Send()|, but targets a process which will accept the invitation 104 // with |IncomingInvitation::AcceptAsync()| instead of |Accept()|. 105 static void SendAsync(OutgoingInvitation invitation, 106 base::ProcessHandle target_process, 107 PlatformChannelEndpoint channel_endpoint, 108 const ProcessErrorCallback& error_callback = {}); 109 110 // Sends an isolated invitation over |endpoint|. The process at the other 111 // endpoint must use |IncomingInvitation::AcceptIsolated()| to accept the 112 // invitation. 113 // 114 // Isolated invitations must be used in lieu of regular invitations in cases 115 // where both of the processes being connected already belong to independent 116 // multiprocess graphs. 117 // 118 // Such connections are limited in functionality: 119 // 120 // * Platform handles may not be transferrable between the processes 121 // 122 // * Pipes sent between the processes may not be subsequently transferred to 123 // other processes in each others' process graph. 124 // 125 // Only one concurrent isolated connection is supported between any two 126 // processes. 127 // 128 // Unlike |Send()| above, isolated invitations automatically have a single 129 // message pipe attached and this is the only attachment allowed. The local 130 // end of the attached pipe is returned here. 131 // 132 // If |connection_name| is non-empty, any previously established isolated 133 // connection using the same name will be disconnected. 134 static ScopedMessagePipeHandle SendIsolated( 135 PlatformChannelEndpoint channel_endpoint, 136 base::StringPiece connection_name = {}); 137 138 // Similar to above but sends |invitation| via |server_endpoint|, which should 139 // correspond to a |PlatformChannelServerEndpoint| taken from a 140 // |NamedPlatformChannel|. 141 // 142 // If |connection_name| is non-empty, any previously established isolated 143 // connection using the same name will be disconnected. 144 static ScopedMessagePipeHandle SendIsolated( 145 PlatformChannelServerEndpoint server_endpoint, 146 base::StringPiece connection_name = {}); 147 148 private: 149 ScopedInvitationHandle handle_; 150 151 DISALLOW_COPY_AND_ASSIGN(OutgoingInvitation); 152 }; 153 154 // An IncomingInvitation can be accepted by an invited process by calling 155 // |IncomingInvitation::Accept()|. Once accepted, the invitation can be used 156 // to extract attached message pipes by name. 157 class MOJO_CPP_SYSTEM_EXPORT IncomingInvitation { 158 public: 159 IncomingInvitation(); 160 IncomingInvitation(IncomingInvitation&& other); 161 explicit IncomingInvitation(ScopedInvitationHandle handle); 162 ~IncomingInvitation(); 163 164 IncomingInvitation& operator=(IncomingInvitation&& other); 165 166 // Accepts an incoming invitation from |channel_endpoint|. If the invitation 167 // was sent using one end of a |PlatformChannel|, |channel_endpoint| should be 168 // the other end of that channel. If the invitation was sent using a 169 // |PlatformChannelServerEndpoint|, then |channel_endpoint| should be created 170 // by |NamedPlatformChannel::ConnectToServer|. 171 // 172 // Note that this performs blocking I/O on the calling thread. 173 static IncomingInvitation Accept( 174 PlatformChannelEndpoint channel_endpoint, 175 MojoAcceptInvitationFlags flags = MOJO_ACCEPT_INVITATION_FLAG_NONE); 176 177 // Like above, but does not perform any blocking I/O. Not all platforms and 178 // sandbox configurations are compatible with this API. In such cases, the 179 // synchronous |Accept()| above should be used. 180 static IncomingInvitation AcceptAsync( 181 PlatformChannelEndpoint channel_endpoint); 182 183 // Accepts an incoming isolated invitation from |channel_endpoint|. See 184 // notes on |OutgoingInvitation::SendIsolated()|. 185 static ScopedMessagePipeHandle AcceptIsolated( 186 PlatformChannelEndpoint channel_endpoint); 187 188 // Extracts an attached message pipe from this invitation. This may succeed 189 // even if no such pipe was attached, though the extracted pipe will 190 // eventually observe peer closure. 191 ScopedMessagePipeHandle ExtractMessagePipe(base::StringPiece name); 192 193 // Same as above but allows use of an integer name for convenience. 194 ScopedMessagePipeHandle ExtractMessagePipe(uint64_t name); 195 196 private: 197 ScopedInvitationHandle handle_; 198 199 DISALLOW_COPY_AND_ASSIGN(IncomingInvitation); 200 }; 201 202 } // namespace mojo 203 204 #endif // MOJO_PUBLIC_CPP_SYSTEM_INVITATION_H_ 205