Home | History | Annotate | Download | only in system
      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:
     33   InvitationHandle() {}
     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