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