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/location.h" | |
13 #include "base/memory/ptr_util.h" | |
14 #include "base/path_service.h" | |
15 #include "base/process/launch.h" | |
16 #include "base/process/process.h" | |
17 #include "base/strings/string_number_conversions.h" | |
18 #include "base/task_scheduler/post_task.h" | |
19 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_client_info_win.h" | |
20 #include "chrome/installer/util/install_util.h" | |
21 #include "components/chrome_cleaner/public/constants/constants.h" | |
22 #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" | |
23 #include "components/version_info/version_info.h" | |
24 #include "content/public/browser/browser_thread.h" | |
25 #include "mojo/edk/embedder/connection_params.h" | |
26 #include "mojo/edk/embedder/embedder.h" | |
27 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h" | |
28 #include "mojo/edk/embedder/platform_channel_pair.h" | |
29 #include "mojo/edk/embedder/transport_protocol.h" | |
30 #include "mojo/public/cpp/system/message_pipe.h" | |
31 | |
32 using chrome_cleaner::mojom::ChromePrompt; | |
33 using chrome_cleaner::mojom::ChromePromptRequest; | |
34 using content::BrowserThread; | |
35 | |
36 namespace safe_browsing { | |
37 | |
38 void RunChromeCleanerAndReplyWithExitCode( | |
39 const base::FilePath& executable_path, | |
40 bool metrics_enabled, | |
41 bool sber_enabled, | |
42 ChromePromptImpl::OnPromptUserCallback on_prompt_user, | |
43 base::OnceClosure on_connection_closed, | |
44 base::OnceClosure on_connection_error, | |
45 base::Callback<void(int /*exit code*/)> done_callback) { | |
46 auto cleaner_runner = base::MakeShared<ChromeCleanerRunner>( | |
47 executable_path, metrics_enabled, sber_enabled, std::move(on_prompt_user), | |
48 std::move(on_connection_closed), std::move(on_connection_error)); | |
49 auto launch_and_wait = | |
50 base::Bind(&ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread, | |
51 cleaner_runner); | |
52 base::PostTaskWithTraitsAndReplyWithResult( | |
53 FROM_HERE, | |
54 // LaunchAndWaitForExitOnBackgroundThread creates (MayBlock()) and joins | |
55 // (WithBaseSyncPrimitives()) a process. | |
56 {base::MayBlock(), base::WithBaseSyncPrimitives(), | |
57 base::TaskPriority::BACKGROUND, | |
58 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, | |
59 std::move(launch_and_wait), done_callback); | |
60 } | |
61 | |
62 ChromeCleanerRunner::ChromeCleanerRunner( | |
63 const base::FilePath& executable_path, | |
64 bool metrics_enabled, | |
65 bool sber_enabled, | |
66 ChromePromptImpl::OnPromptUserCallback on_prompt_user, | |
67 base::OnceClosure on_connection_closed, | |
68 base::OnceClosure on_connection_error) | |
69 : command_line_(executable_path), | |
70 on_prompt_user_(std::move(on_prompt_user)), | |
71 on_connection_closed_(std::move(on_connection_closed)), | |
72 on_connection_error_(std::move(on_connection_error)) { | |
73 DCHECK(on_prompt_user_); | |
74 DCHECK(on_connection_closed_); | |
75 DCHECK(on_connection_error_); | |
76 DCHECK(!executable_path.empty()); | |
77 | |
78 // Add the non-IPC switches that should be passed to the Cleaner process. | |
79 | |
80 // Add switches that pass information about this Chrome installation. | |
ftirelo
2017/05/18 18:27:50
No kChromePromptSwitch?
alito
2017/05/18 23:01:17
Well, the user hasn't been prompted at this point.
| |
81 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeVersionSwitch, | |
82 version_info::GetVersionNumber()); | |
83 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeChannelSwitch, | |
84 base::IntToString(ChannelAsInt())); | |
85 base::FilePath chrome_exe_path; | |
86 PathService::Get(base::FILE_EXE, &chrome_exe_path); | |
87 command_line_.AppendSwitchPath(chrome_cleaner::kChromeExePathSwitch, | |
88 chrome_exe_path); | |
89 if (!InstallUtil::IsPerUserInstall()) | |
90 command_line_.AppendSwitch(chrome_cleaner::kChromeSystemInstallSwitch); | |
91 | |
92 // If metrics is enabled, we can enable crash reporting in the Chrome Cleaner | |
93 // process. | |
94 if (metrics_enabled) { | |
95 command_line_.AppendSwitch(chrome_cleaner::kUmaUserSwitch); | |
96 command_line_.AppendSwitch(chrome_cleaner::kEnableCrashReportingSwitch); | |
97 } | |
98 | |
99 // Enable losg upload for users who have opted into safe browsing extended | |
100 // reporting V2. | |
101 if (sber_enabled) { | |
102 command_line_.AppendSwitch( | |
103 chrome_cleaner::kExtendedSafeBrowsingEnabledSwitch); | |
ftirelo
2017/05/18 18:27:50
As discussed, this can become kCleanerLoggingEnabl
alito
2017/05/18 23:01:17
Done.
| |
104 } | |
105 } | |
106 | |
107 int ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread() { | |
108 mojo::edk::OutgoingBrokerClientInvitation invitation; | |
109 std::string mojo_pipe_token = mojo::edk::GenerateRandomToken(); | |
110 mojo::ScopedMessagePipeHandle mojo_pipe = | |
111 invitation.AttachMessagePipe(mojo_pipe_token); | |
112 command_line_.AppendSwitchASCII(chrome_cleaner::kChromeMojoPipeTokenSwitch, | |
113 mojo_pipe_token); | |
114 command_line_.AppendSwitchASCII( | |
115 chrome_cleaner::kExecutionModeSwitch, | |
116 base::IntToString( | |
117 static_cast<int>(chrome_cleaner::ExecutionMode::kScanning))); | |
ftirelo
2017/05/18 18:27:50
Please add this in the method above with the other
alito
2017/05/18 23:01:17
Done.
| |
118 | |
119 mojo::edk::PlatformChannelPair channel; | |
120 base::HandlesToInheritVector handles_to_inherit; | |
121 channel.PrepareToPassClientHandleToChildProcess(&command_line_, | |
122 &handles_to_inherit); | |
123 base::LaunchOptions launch_options; | |
124 launch_options.handles_to_inherit = &handles_to_inherit; | |
125 | |
126 base::Process cleaner_process = | |
127 base::LaunchProcess(command_line_, launch_options); | |
128 | |
129 if (!cleaner_process.IsValid()) | |
130 return kNotLaunchedExitCode; | |
131 | |
132 // ChromePromptImpl tasks will need to run on the IO thread. There is no | |
133 // need to synchronize its creation, since the client end will wait for this | |
134 // initialization to be done before sending requests. | |
135 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
136 ->PostTask(FROM_HERE, | |
137 base::BindOnce(&ChromeCleanerRunner::CreateChromePromptImpl, | |
138 base::RetainedRef(this), | |
139 chrome_cleaner::mojom::ChromePromptRequest( | |
140 std::move(mojo_pipe)))); | |
141 | |
142 // mojo::edk::ProcessErrorCallback on_connection_error = | |
143 // base::Bind(&OnConnectionError); | |
ftirelo
2017/05/18 18:27:50
Please delete.
alito
2017/05/18 23:01:17
Done.
| |
144 invitation.Send( | |
145 cleaner_process.Handle(), | |
146 mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy, | |
147 channel.PassServerHandle()), | |
148 base::Bind(&ChromeCleanerRunner::OnConnectionError, | |
149 base::RetainedRef(this))); | |
150 | |
151 int exit_code = kNotLaunchedExitCode; | |
152 bool success = cleaner_process.WaitForExit(&exit_code); | |
153 DCHECK(success); | |
154 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
155 ->PostTask(FROM_HERE, | |
156 base::Bind(&ChromeCleanerRunner::ReleaseChromePromptImpl, | |
157 base::RetainedRef(this))); | |
158 return exit_code; | |
159 } | |
160 | |
161 ChromeCleanerRunner::~ChromeCleanerRunner() = default; | |
162 | |
163 void ChromeCleanerRunner::CreateChromePromptImpl( | |
164 ChromePromptRequest chrome_prompt_request) { | |
165 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
ftirelo
2017/05/18 18:27:50
Worth DCHECK'ing that the feature is enabled?
alito
2017/05/18 23:01:17
Since this class should only be used if the featur
| |
166 DCHECK(!chrome_prompt_impl_); | |
167 | |
168 chrome_prompt_impl_ = base::MakeUnique<ChromePromptImpl>( | |
169 std::move(chrome_prompt_request), | |
170 base::Bind(&ChromeCleanerRunner::OnConnectionClosed, | |
171 base::RetainedRef(this)), | |
172 base::Bind(&ChromeCleanerRunner::OnPromptUser, base::RetainedRef(this))); | |
173 } | |
174 | |
175 void ChromeCleanerRunner::ReleaseChromePromptImpl() { | |
176 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
177 DCHECK(chrome_prompt_impl_); | |
178 | |
179 chrome_prompt_impl_.release(); | |
180 } | |
181 | |
182 void ChromeCleanerRunner::OnPromptUser( | |
183 std::unique_ptr<std::set<base::FilePath>> files_to_delete, | |
184 ChromePrompt::PromptUserCallback prompt_user_callback) { | |
185 if (on_prompt_user_) { | |
186 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
187 ->PostTask(FROM_HERE, base::Bind(std::move(on_prompt_user_), | |
188 base::Passed(&files_to_delete), | |
189 base::Passed(&prompt_user_callback))); | |
190 } | |
191 } | |
192 | |
193 void ChromeCleanerRunner::OnConnectionClosed() { | |
194 if (on_connection_closed_) { | |
195 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
196 ->PostTask(FROM_HERE, std::move(on_connection_closed_)); | |
197 } | |
198 } | |
199 | |
200 void ChromeCleanerRunner::OnConnectionError(const std::string& error) { | |
201 if (on_connection_error_) { | |
202 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) | |
203 ->PostTask(FROM_HERE, std::move(on_connection_error_)); | |
204 } | |
205 } | |
206 | |
207 } // namespace safe_browsing | |
OLD | NEW |