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