Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win. h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/base_paths.h" | |
| 10 #include "base/bind.h" | |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/feature_list.h" | |
| 13 #include "base/location.h" | |
| 14 #include "base/memory/ptr_util.h" | |
| 15 #include "base/path_service.h" | |
| 16 #include "base/process/launch.h" | |
| 17 #include "base/process/process.h" | |
| 18 #include "base/strings/string_number_conversions.h" | |
| 19 #include "base/task_scheduler/post_task.h" | |
| 20 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_client_info_win.h" | |
| 21 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h" | |
| 22 #include "chrome/installer/util/install_util.h" | |
| 23 #include "components/chrome_cleaner/public/constants/constants.h" | |
| 24 #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" | |
| 25 #include "components/version_info/version_info.h" | |
| 26 #include "content/public/browser/browser_thread.h" | |
| 27 #include "mojo/edk/embedder/connection_params.h" | |
| 28 #include "mojo/edk/embedder/embedder.h" | |
| 29 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h" | |
| 30 #include "mojo/edk/embedder/platform_channel_pair.h" | |
| 31 #include "mojo/edk/embedder/transport_protocol.h" | |
| 32 #include "mojo/public/cpp/system/message_pipe.h" | |
| 33 | |
| 34 using chrome_cleaner::mojom::ChromePrompt; | |
| 35 using chrome_cleaner::mojom::ChromePromptRequest; | |
| 36 using content::BrowserThread; | |
| 37 | |
| 38 namespace safe_browsing { | |
| 39 | |
| 40 // static | |
| 41 void ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode( | |
| 42 const base::FilePath& executable_path, | |
| 43 const SwReporterInvocation& reporter_invocation, | |
| 44 bool metrics_enabled, | |
| 45 bool cleaner_logs_enabled, | |
| 46 ChromePromptImpl::OnPromptUser on_prompt_user, | |
| 47 base::OnceClosure on_connection_closed, | |
| 48 base::OnceClosure on_connection_error, | |
| 49 ChromeCleanerRunner::ProcessDoneCallback on_process_done_) { | |
|
Joe Mason
2017/05/19 22:02:25
on_process_done_ shouldn't have a trailing _
alito
2017/05/22 23:26:30
Done.
| |
| 50 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
|
Joe Mason
2017/05/19 22:02:25
I don't think this is necessary. We don't really c
alito
2017/05/22 23:26:30
Done.
| |
| 51 | |
| 52 auto cleaner_runner = make_scoped_refptr(new ChromeCleanerRunner( | |
|
csharp
2017/05/19 20:44:17
I wonder if it'd be cleaner to move the creation o
alito
2017/05/22 23:26:31
One benefit of having the static function create t
| |
| 53 executable_path, reporter_invocation, metrics_enabled, | |
| 54 cleaner_logs_enabled, std::move(on_prompt_user), | |
| 55 std::move(on_connection_closed), std::move(on_connection_error), | |
| 56 std::move(on_process_done_))); | |
| 57 auto launch_and_wait = base::BindOnce( | |
| 58 &ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread, | |
| 59 cleaner_runner); | |
| 60 auto process_done = | |
| 61 base::BindOnce(&ChromeCleanerRunner::OnProcessDone, cleaner_runner); | |
| 62 base::PostTaskWithTraitsAndReplyWithResult( | |
| 63 FROM_HERE, | |
| 64 // LaunchAndWaitForExitOnBackgroundThread creates (MayBlock()) and joins | |
| 65 // (WithBaseSyncPrimitives()) a process. | |
| 66 {base::MayBlock(), base::WithBaseSyncPrimitives(), | |
| 67 base::TaskPriority::BACKGROUND, | |
| 68 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, | |
| 69 std::move(launch_and_wait), std::move(process_done)); | |
| 70 } | |
| 71 | |
| 72 ChromeCleanerRunner::ChromeCleanerRunner( | |
| 73 const base::FilePath& executable_path, | |
| 74 const SwReporterInvocation& reporter_invocation, | |
| 75 bool metrics_enabled, | |
| 76 bool cleaner_logs_enabled, | |
| 77 ChromePromptImpl::OnPromptUser on_prompt_user, | |
| 78 base::OnceClosure on_connection_closed, | |
| 79 base::OnceClosure on_connection_error, | |
| 80 ProcessDoneCallback on_process_done) | |
| 81 : command_line_(executable_path), | |
| 82 on_prompt_user_(std::move(on_prompt_user)), | |
| 83 on_connection_closed_(std::move(on_connection_closed)), | |
| 84 on_connection_error_(std::move(on_connection_error)), | |
| 85 on_process_done_(std::move(on_process_done)) { | |
| 86 DCHECK(base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature)); | |
| 87 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
|
Joe Mason
2017/05/19 22:02:25
base::SequenceChecker can replace this.
You'd als
alito
2017/05/22 23:26:30
Now using ThreadTaskRunnerHandle::Get() to get a S
| |
| 88 DCHECK(on_prompt_user_); | |
| 89 DCHECK(on_connection_closed_); | |
| 90 DCHECK(on_connection_error_); | |
| 91 DCHECK(!executable_path.empty()); | |
| 92 | |
| 93 // Add the non-IPC switches that should be passed to the Cleaner process. | |
| 94 | |
| 95 // Add switches that pass information about this Chrome installation. | |
| 96 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeVersionSwitch, | |
| 97 version_info::GetVersionNumber()); | |
| 98 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeChannelSwitch, | |
| 99 base::IntToString(ChannelAsInt())); | |
| 100 base::FilePath chrome_exe_path; | |
| 101 PathService::Get(base::FILE_EXE, &chrome_exe_path); | |
| 102 command_line_.AppendSwitchPath(chrome_cleaner::kChromeExePathSwitch, | |
| 103 chrome_exe_path); | |
| 104 if (!InstallUtil::IsPerUserInstall()) | |
| 105 command_line_.AppendSwitch(chrome_cleaner::kChromeSystemInstallSwitch); | |
| 106 | |
| 107 // Start the cleaner process in scanning mode. | |
| 108 command_line_.AppendSwitchASCII( | |
| 109 chrome_cleaner::kExecutionModeSwitch, | |
| 110 base::IntToString( | |
| 111 static_cast<int>(chrome_cleaner::ExecutionMode::kScanning))); | |
| 112 | |
| 113 // If set, forward the engine flag from the reporter. Otherwise, set the | |
| 114 // engine flag explicitly to 1. | |
| 115 command_line_.AppendSwitchASCII( | |
| 116 chrome_cleaner::kEngineSwitch, | |
| 117 reporter_invocation.command_line.HasSwitch(chrome_cleaner::kEngineSwitch) | |
| 118 ? reporter_invocation.command_line.GetSwitchValueASCII( | |
| 119 chrome_cleaner::kEngineSwitch) | |
| 120 : base::IntToString(1)); | |
| 121 | |
| 122 // If metrics is enabled, we can enable crash reporting in the Chrome Cleaner | |
| 123 // process. | |
| 124 if (metrics_enabled) { | |
| 125 command_line_.AppendSwitch(chrome_cleaner::kUmaUserSwitch); | |
| 126 command_line_.AppendSwitch(chrome_cleaner::kEnableCrashReportingSwitch); | |
| 127 } | |
| 128 | |
| 129 // Enable logs upload for users who have opted into safe browsing extended | |
| 130 // reporting v2. | |
| 131 if (cleaner_logs_enabled) | |
| 132 command_line_.AppendSwitch(chrome_cleaner::kEnableCleanerLoggingSwitch); | |
| 133 } | |
| 134 | |
| 135 int ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread() { | |
| 136 mojo::edk::OutgoingBrokerClientInvitation invitation; | |
| 137 std::string mojo_pipe_token = mojo::edk::GenerateRandomToken(); | |
| 138 mojo::ScopedMessagePipeHandle mojo_pipe = | |
| 139 invitation.AttachMessagePipe(mojo_pipe_token); | |
| 140 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeMojoPipeTokenSwitch, | |
| 141 mojo_pipe_token); | |
| 142 | |
| 143 mojo::edk::PlatformChannelPair channel; | |
| 144 base::HandlesToInheritVector handles_to_inherit; | |
| 145 channel.PrepareToPassClientHandleToChildProcess(&command_line_, | |
| 146 &handles_to_inherit); | |
| 147 base::LaunchOptions launch_options; | |
| 148 launch_options.handles_to_inherit = &handles_to_inherit; | |
| 149 | |
| 150 base::Process cleaner_process = | |
| 151 base::LaunchProcess(command_line_, launch_options); | |
| 152 | |
| 153 if (!cleaner_process.IsValid()) | |
| 154 return kNotLaunchedExitCode; | |
|
csharp
2017/05/19 20:44:17
I wonder if it might be cleaner to have bool in a
alito
2017/05/22 23:26:30
Done.
| |
| 155 | |
| 156 // ChromePromptImpl tasks will need to run on the IO thread. There is no | |
| 157 // need to synchronize its creation, since the client end will wait for this | |
| 158 // initialization to be done before sending requests. | |
| 159 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
| 160 ->PostTask(FROM_HERE, | |
| 161 base::BindOnce(&ChromeCleanerRunner::CreateChromePromptImpl, | |
| 162 base::RetainedRef(this), | |
| 163 chrome_cleaner::mojom::ChromePromptRequest( | |
| 164 std::move(mojo_pipe)))); | |
| 165 | |
| 166 invitation.Send( | |
| 167 cleaner_process.Handle(), | |
| 168 mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy, | |
| 169 channel.PassServerHandle()), | |
| 170 base::Bind(&ChromeCleanerRunner::OnConnectionError, | |
| 171 base::RetainedRef(this))); | |
| 172 | |
| 173 int exit_code = kNotLaunchedExitCode; | |
| 174 bool success = cleaner_process.WaitForExit(&exit_code); | |
| 175 DCHECK(success); | |
| 176 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
| 177 ->PostTask(FROM_HERE, | |
| 178 base::Bind(&ChromeCleanerRunner::ReleaseChromePromptImpl, | |
| 179 base::RetainedRef(this))); | |
| 180 return exit_code; | |
| 181 } | |
| 182 | |
| 183 ChromeCleanerRunner::~ChromeCleanerRunner() { | |
| 184 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
|
Joe Mason
2017/05/19 22:02:25
Can you also DCHECK that chrome_prompt_impl_ is nu
alito
2017/05/22 23:26:31
Done.
| |
| 185 } | |
| 186 | |
| 187 void ChromeCleanerRunner::CreateChromePromptImpl( | |
| 188 ChromePromptRequest chrome_prompt_request) { | |
| 189 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 190 DCHECK(!chrome_prompt_impl_); | |
| 191 | |
| 192 chrome_prompt_impl_ = base::MakeUnique<ChromePromptImpl>( | |
| 193 std::move(chrome_prompt_request), | |
| 194 base::Bind(&ChromeCleanerRunner::OnConnectionClosed, | |
| 195 base::RetainedRef(this)), | |
| 196 base::Bind(&ChromeCleanerRunner::OnPromptUser, base::RetainedRef(this))); | |
| 197 } | |
| 198 | |
| 199 void ChromeCleanerRunner::ReleaseChromePromptImpl() { | |
| 200 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 201 DCHECK(chrome_prompt_impl_); | |
| 202 | |
| 203 chrome_prompt_impl_.release(); | |
| 204 } | |
| 205 | |
| 206 void ChromeCleanerRunner::OnPromptUser( | |
| 207 std::unique_ptr<std::set<base::FilePath>> files_to_delete, | |
| 208 ChromePrompt::PromptUserCallback prompt_user_callback) { | |
| 209 if (on_prompt_user_) { | |
| 210 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
| 211 ->PostTask(FROM_HERE, | |
| 212 base::BindOnce(std::move(on_prompt_user_), | |
| 213 base::Passed(&files_to_delete), | |
| 214 base::Passed(&prompt_user_callback))); | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 void ChromeCleanerRunner::OnConnectionClosed() { | |
| 219 if (on_connection_closed_) { | |
| 220 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
| 221 ->PostTask(FROM_HERE, std::move(on_connection_closed_)); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 void ChromeCleanerRunner::OnConnectionError(const std::string& error) { | |
| 226 if (on_connection_error_) { | |
| 227 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
| 228 ->PostTask(FROM_HERE, std::move(on_connection_error_)); | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 void ChromeCleanerRunner::OnProcessDone(int exit_code) { | |
| 233 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 234 | |
| 235 if (!on_process_done_) | |
| 236 return; | |
| 237 std::move(on_process_done_).Run(exit_code); | |
| 238 } | |
| 239 | |
| 240 } // namespace safe_browsing | |
| OLD | NEW |