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 CHROME_CHROME_CLEANER_IPC_IPC_TEST_UTIL_H_ 6 #define CHROME_CHROME_CLEANER_IPC_IPC_TEST_UTIL_H_ 7 8 #include <memory> 9 #include <string> 10 11 #include "base/callback_forward.h" 12 #include "base/command_line.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/process/launch.h" 15 #include "base/process/process.h" 16 #include "base/time/time.h" 17 #include "chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h" 18 #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" 19 #include "chrome/chrome_cleaner/test/child_process_logger.h" 20 #include "mojo/public/cpp/platform/platform_channel.h" 21 #include "mojo/public/cpp/system/invitation.h" 22 #include "mojo/public/cpp/system/message_pipe.h" 23 24 namespace chrome_cleaner { 25 26 typedef base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle mojo_pipe)> 27 CreateImplCallback; 28 29 class ParentProcess : public base::RefCountedThreadSafe<ParentProcess> { 30 public: 31 explicit ParentProcess(scoped_refptr<MojoTaskRunner> mojo_task_runner); 32 33 bool LaunchConnectedChildProcess(const std::string& child_main_function, 34 int32_t* exit_code); 35 36 bool LaunchConnectedChildProcess(const std::string& child_main_function, 37 base::TimeDelta timeout, 38 int32_t* exit_code); 39 40 void AppendSwitch(const std::string& switch_string); 41 void AppendSwitch(const std::string& switch_string, const std::string& value); 42 void AppendSwitchNative(const std::string& switch_string, 43 const std::wstring& value); 44 void AppendSwitchPath(const std::string& switch_string, 45 const base::FilePath& value); 46 void AppendSwitchHandleToShare(const std::string& switch_string, 47 HANDLE handle); 48 49 // The following methods are called during the launch sequence. They are 50 // public so they can be called from helper classes. 51 void CreateImplOnIPCThread(mojo::ScopedMessagePipeHandle mojo_pipe); 52 void DestroyImplOnIPCThread(); 53 void CreateMojoPipe(base::CommandLine* command_line, 54 base::HandlesToInheritVector* handles_to_inherit); 55 void ConnectMojoPipe(base::Process child_process); 56 extra_handles_to_inherit()57 base::HandlesToInheritVector extra_handles_to_inherit() const { 58 return extra_handles_to_inherit_; 59 } 60 child_process_logger()61 const ChildProcessLogger& child_process_logger() const { 62 return child_process_logger_; 63 } 64 65 protected: 66 friend base::RefCountedThreadSafe<ParentProcess>; 67 virtual ~ParentProcess(); 68 69 // This is called on the IPC thread. 70 virtual void CreateImpl(mojo::ScopedMessagePipeHandle mojo_pipe) = 0; 71 virtual void DestroyImpl() = 0; 72 73 // Subclasses can override this to launch the child in different ways, such 74 // as in the sandbox. Subclasses should call CreateMojoPipe before the 75 // subprocess is spawned and ConnectMojoPipe afterward. 76 virtual bool PrepareAndLaunchTestChildProcess( 77 const std::string& child_main_function); 78 79 scoped_refptr<MojoTaskRunner> mojo_task_runner(); 80 81 base::CommandLine command_line_; 82 base::HandlesToInheritVector extra_handles_to_inherit_; 83 ChildProcessLogger child_process_logger_; 84 85 private: 86 scoped_refptr<MojoTaskRunner> mojo_task_runner_; 87 mojo::OutgoingInvitation outgoing_invitation_; 88 mojo::ScopedMessagePipeHandle mojo_pipe_; 89 mojo::PlatformChannel mojo_channel_; 90 base::Process child_process_; 91 }; 92 93 class SandboxedParentProcess : public ParentProcess { 94 public: 95 explicit SandboxedParentProcess( 96 scoped_refptr<MojoTaskRunner> mojo_task_runner); 97 98 protected: 99 friend base::RefCountedThreadSafe<SandboxedParentProcess>; 100 ~SandboxedParentProcess() override; 101 102 bool PrepareAndLaunchTestChildProcess( 103 const std::string& child_main_function) override; 104 }; 105 106 class ChildProcess : public base::RefCountedThreadSafe<ChildProcess> { 107 public: 108 explicit ChildProcess(scoped_refptr<MojoTaskRunner> mojo_task_runner); 109 110 mojo::ScopedMessagePipeHandle CreateMessagePipeFromCommandLine(); 111 112 std::string mojo_pipe_token() const; 113 command_line()114 const base::CommandLine& command_line() const { return *command_line_; } 115 116 // This will drop all privileges if the child process is running in a 117 // sandbox. If not, it will do nothing. 118 void LowerToken() const; 119 120 protected: 121 friend base::RefCountedThreadSafe<ChildProcess>; 122 virtual ~ChildProcess(); 123 124 scoped_refptr<MojoTaskRunner> mojo_task_runner_; 125 126 private: 127 base::CommandLine* command_line_; 128 129 // This will be true iff the process is running in a sandbox and 130 // TargetServices was initialized successfully. 131 bool target_services_initialized_ = false; 132 }; 133 134 class ChromePromptIPCTestErrorHandler : public ChromePromptIPC::ErrorHandler { 135 public: 136 ChromePromptIPCTestErrorHandler(base::OnceClosure on_closed, 137 base::OnceClosure on_closed_after_done); 138 139 ~ChromePromptIPCTestErrorHandler() override; 140 141 void OnConnectionClosed() override; 142 void OnConnectionClosedAfterDone() override; 143 144 private: 145 base::OnceClosure on_closed_; 146 base::OnceClosure on_closed_after_done_; 147 }; 148 149 } // namespace chrome_cleaner 150 151 #endif // CHROME_CHROME_CLEANER_IPC_IPC_TEST_UTIL_H_ 152