1 // Copyright 2017 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_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ 6 #define MOJO_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ 7 8 #include <string> 9 10 #include "base/callback.h" 11 #include "base/macros.h" 12 #include "base/process/process_handle.h" 13 #include "mojo/edk/embedder/connection_params.h" 14 #include "mojo/edk/embedder/scoped_platform_handle.h" 15 #include "mojo/edk/system/system_impl_export.h" 16 #include "mojo/public/cpp/system/message_pipe.h" 17 18 namespace mojo { 19 namespace edk { 20 21 using ProcessErrorCallback = base::Callback<void(const std::string& error)>; 22 23 // Represents a potential connection to an external process. Use this object 24 // to make other processes reachable from this one via Mojo IPC. Typical usage 25 // might look something like: 26 // 27 // PendingProcessConnection connection; 28 // 29 // std::string pipe_token; 30 // ScopedMessagePipeHandle pipe = connection.CreateMessagePipe(&pipe_token); 31 // 32 // // New pipes to the process are fully functional and can be used right 33 // // away, even if the process doesn't exist yet. 34 // GoDoSomethingInteresting(std::move(pipe)); 35 // 36 // ScopedPlatformChannelPair channel; 37 // 38 // // Give the pipe token to the child process via command-line. 39 // child_command_line.AppendSwitchASCII("yer-pipe", pipe_token); 40 // 41 // // Magic child process launcher which gives one end of the pipe to the 42 // // new process. 43 // LaunchProcess(child_command_line, channel.PassClientHandle()); 44 // 45 // // Some time later... 46 // connection.Connect(new_process, channel.PassServerHandle()); 47 // 48 // If at any point during the above process, |connection| is destroyed before 49 // Connect() can be called, |pipe| will imminently behave as if its peer has 50 // been closed. 51 // 52 // Otherwise, if the remote process in this example eventually calls: 53 // 54 // mojo::edk::SetParentPipeHandle(std::move(client_channel_handle)); 55 // 56 // std::string token = command_line.GetSwitchValueASCII("yer-pipe"); 57 // ScopedMessagePipeHandle pipe = mojo::edk::CreateChildMessagePipe(token); 58 // 59 // it will be connected to this process, and its |pipe| will be connected to 60 // this process's |pipe|. 61 // 62 // If the remote process exits or otherwise closes its client channel handle 63 // before calling CreateChildMessagePipe for a given message pipe token, 64 // this process's end of the corresponding message pipe will imminently behave 65 // as if its peer has been closed. 66 // 67 class MOJO_SYSTEM_IMPL_EXPORT PendingProcessConnection { 68 public: 69 PendingProcessConnection(); 70 ~PendingProcessConnection(); 71 72 // Creates a message pipe associated with a new globally unique string value 73 // which will be placed in |*token|. 74 // 75 // The other end of the new pipe is obtainable in the remote process (or in 76 // this process, to facilitate "single-process mode" in some applications) by 77 // passing the new |*token| value to mojo::edk::CreateChildMessagePipe. It's 78 // the caller's responsibility to communicate the value of |*token| to the 79 // remote process by any means available, e.g. a command-line argument on 80 // process launch, or some other out-of-band communication channel for an 81 // existing process. 82 // 83 // NOTES: This may be called any number of times to create multiple message 84 // pipes to the same remote process. This call ALWAYS succeeds, returning 85 // a valid message pipe handle and populating |*token| with a new unique 86 // string value. 87 ScopedMessagePipeHandle CreateMessagePipe(std::string* token); 88 89 // Connects to the process. This must be called at most once, with the process 90 // handle in |process|. 91 // 92 // |connection_param| contains the platform handle of an OS pipe which can be 93 // used to communicate with the connected process. The other end of that pipe 94 // must ultimately be passed to mojo::edk::SetParentPipeHandle in the remote 95 // process, and getting that end of the pipe into the other process is the 96 // embedder's responsibility. 97 // 98 // If this method is not called by the time the PendingProcessConnection is 99 // destroyed, it's assumed that the process is unavailable (e.g. process 100 // launch failed or the process has otherwise been terminated early), and 101 // any associated resources, such as remote endpoints of messages pipes 102 // created by CreateMessagePipe above) will be cleaned up at that time. 103 void Connect( 104 base::ProcessHandle process, 105 ConnectionParams connection_params, 106 const ProcessErrorCallback& error_callback = ProcessErrorCallback()); 107 108 private: 109 // A GUID representing a potential new process to be connected to this one. 110 const std::string process_token_; 111 112 // Indicates whether this object has been used to create new message pipes. 113 bool has_message_pipes_ = false; 114 115 // Indicates whether Connect() has been called yet. 116 bool connected_ = false; 117 118 DISALLOW_COPY_AND_ASSIGN(PendingProcessConnection); 119 }; 120 121 } // namespace edk 122 } // namespace mojo 123 124 #endif // MOJO_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ 125