Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc

Issue 2890023005: Chrome Cleaner UI: reporter no longer uses mojo. (Closed)
Patch Set: Nits Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <tuple>
8 #include <utility>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "base/process/launch.h"
13 #include "base/process/process.h"
14 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/test/multiprocess_test.h"
18 #include "base/test/scoped_feature_list.h"
19 #include "base/threading/thread.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_proces s_win.h"
22 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
23 #include "components/chrome_cleaner/public/constants/constants.h"
24 #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/multiprocess_func_list.h"
30
31 namespace safe_browsing {
32 namespace {
33
34 using ::chrome_cleaner::mojom::ChromePrompt;
35 using ::chrome_cleaner::mojom::PromptAcceptance;
36 using ::content::BrowserThread;
37 using ::testing::Bool;
38 using ::testing::Combine;
39 using ::testing::Values;
40 using ChromeMetricsStatus = ChromeCleanerRunner::ChromeMetricsStatus;
41 using CleanerLogsStatus = ChromeCleanerRunner::CleanerLogsStatus;
42
43 enum class ReporterEngine {
44 kUnspecified,
45 kOldEngine,
46 kNewEngine,
47 };
48
49 // Simple test fixture that intercepts the launching of the Chrome Cleaner
50 // process and does not start a separate mock Cleaner process. It will pass an
51 // invalid process handle back to ChromeCleanerRunner. Intended for testing
52 // simple things like command line flags that Chrome sends to the Chrome Cleaner
53 // process.
54 //
55 // Parameters:
56 // - metrics_status (ChromeMetricsStatus): whether Chrome metrics reporting is
57 // enabled
58 // - logs_upload_status (CleanerLogsStatus): whether logs upload in the Cleaner
59 // process should be enabled.
60 // - reporter_engine (ReporterEngine): the type of Cleaner engine specified in
61 // the SwReporterInvocation.
62 class ChromeCleanerRunnerSimpleTest
63 : public testing::TestWithParam<
64 std::tuple<ChromeCleanerRunner::ChromeMetricsStatus,
65 ChromeCleanerRunner::CleanerLogsStatus,
66 ReporterEngine>>,
67 public ChromeCleanerRunnerTestDelegate {
68 public:
69 ChromeCleanerRunnerSimpleTest()
70 : command_line_(base::CommandLine::NO_PROGRAM) {}
71
72 void SetUp() override {
73 std::tie(metrics_status_, logs_upload_status_, reporter_engine_) =
74 GetParam();
75
76 SetChromeCleanerRunnerTestDelegateForTesting(this);
77 scoped_feature_list_.InitAndEnableFeature(kInBrowserCleanerUIFeature);
78 }
79
80 void CallRunChromeCleaner() {
81 SwReporterInvocation reporter_invocation;
82 switch (reporter_engine_) {
83 case ReporterEngine::kUnspecified:
84 // No engine switch.
85 break;
86 case ReporterEngine::kOldEngine:
87 reporter_invocation.command_line.AppendSwitchASCII(
88 chrome_cleaner::kEngineSwitch, "1");
89 break;
90 case ReporterEngine::kNewEngine:
91 reporter_invocation.command_line.AppendSwitchASCII(
92 chrome_cleaner::kEngineSwitch, "2");
93 break;
94 }
95
96 ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
97 base::FilePath(FILE_PATH_LITERAL("cleaner.exe")), reporter_invocation,
98 metrics_status_, logs_upload_status_,
99 base::BindOnce(&ChromeCleanerRunnerSimpleTest::OnPromptUser,
100 base::Unretained(this)),
101 base::BindOnce(&ChromeCleanerRunnerSimpleTest::OnConnectionClosed,
102 base::Unretained(this)),
103 base::BindOnce(&ChromeCleanerRunnerSimpleTest::OnProcessDone,
104 base::Unretained(this)),
105 base::ThreadTaskRunnerHandle::Get());
106 }
107
108 // ChromeCleanerRunnerTestDelegate overrides.
109
110 base::Process LaunchTestProcess(
111 const base::CommandLine& command_line,
112 const base::LaunchOptions& launch_options) override {
113 command_line_ = command_line;
114 // Return an invalid process.
115 return base::Process();
116 }
117
118 // IPC callbacks.
119
120 void OnPromptUser(std::unique_ptr<std::set<base::FilePath>> files_to_delete,
121 ChromePrompt::PromptUserCallback response) {}
122
123 void OnConnectionClosed() {}
124
125 void OnProcessDone(ChromeCleanerRunner::LaunchStatus launch_status) {
126 on_process_done_called_ = true;
127 launch_status_ = launch_status;
128 run_loop_.QuitWhenIdle();
129 }
130
131 protected:
132 content::TestBrowserThreadBundle test_browser_thread_bundle_;
133 base::test::ScopedFeatureList scoped_feature_list_;
134
135 // Test fixture parameters.
136 ChromeCleanerRunner::ChromeMetricsStatus metrics_status_;
137 ChromeCleanerRunner::CleanerLogsStatus logs_upload_status_;
138 ReporterEngine reporter_engine_;
139
140 // Set by LaunchTestProcess.
141 base::CommandLine command_line_;
142
143 // Variables set by OnProcessDone().
144 bool on_process_done_called_ = false;
145 ChromeCleanerRunner::LaunchStatus launch_status_;
146
147 base::RunLoop run_loop_;
148 };
149
150 TEST_P(ChromeCleanerRunnerSimpleTest, LaunchParams) {
151 CallRunChromeCleaner();
152 run_loop_.Run();
153
154 EXPECT_TRUE(on_process_done_called_);
155
156 EXPECT_EQ(
157 command_line_.GetSwitchValueASCII(chrome_cleaner::kExecutionModeSwitch),
158 base::IntToString(
159 static_cast<int>(chrome_cleaner::ExecutionMode::kScanning)));
160
161 // Ensure that the engine flag is always set and that it correctly reflects
162 // the value of the same flag in the SwReporterInvocation() that was passed to
163 // ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(). In the tests,
164 // the engine flag in the SwReporterInvocation is controlled by the value of
165 // |reporter_engine_|.
166 //
167 // If the engine switch is missing in reporter invocation, it should still be
168 // explicitly set to the value "1" for the Cleaner.
169 std::string expected_engine_switch =
170 reporter_engine_ == ReporterEngine::kNewEngine ? "2" : "1";
171 EXPECT_EQ(command_line_.GetSwitchValueASCII(chrome_cleaner::kEngineSwitch),
172 expected_engine_switch);
173
174 EXPECT_EQ(metrics_status_ == ChromeMetricsStatus::kEnabled,
175 command_line_.HasSwitch(chrome_cleaner::kUmaUserSwitch));
176 EXPECT_EQ(
177 metrics_status_ == ChromeMetricsStatus::kEnabled,
178 command_line_.HasSwitch(chrome_cleaner::kEnableCrashReportingSwitch));
179
180 EXPECT_EQ(
181 logs_upload_status_ == CleanerLogsStatus::kUploadEnabled,
182 command_line_.HasSwitch(chrome_cleaner::kEnableCleanerLoggingSwitch));
183 }
184
185 INSTANTIATE_TEST_CASE_P(
186 All,
187 ChromeCleanerRunnerSimpleTest,
188 Combine(Values(ChromeCleanerRunner::ChromeMetricsStatus::kEnabled,
189 ChromeCleanerRunner::ChromeMetricsStatus::kDisabled),
190 Values(ChromeCleanerRunner::CleanerLogsStatus::kUploadEnabled,
191 ChromeCleanerRunner::CleanerLogsStatus::kUploadDisabled),
192 Values(ReporterEngine::kUnspecified,
193 ReporterEngine::kOldEngine,
194 ReporterEngine::kNewEngine)));
195
196 // Enum to be used as parameter for the ChromeCleanerRunnerTest fixture below.
197 enum class UwsFoundState {
198 kNoUwsFound,
199 kUwsFoundRebootRequired,
200 kUwsFoundNoRebootRequired,
201 };
202
203 // Test fixture for testing ChromeCleanerRunner with a mock Chrome Cleaner
204 // process.
205 //
206 // Parameters:
207 //
208 // - uws_found_state (UwsFoundState): Whether the Chrome Cleaner process should
209 // find UwS on the system and if so whether reboot is required.
210 // - crash_point (CrashPoint): a single crash point where the Chrome Cleaner
211 // process will crash. See the MockChromeCleanerProcess documentation for
212 // possible values.
213 // - prompt_acceptance_to_send (PromptAcceptance): the prompt acceptance value
214 // that Chrome should send to the Chrome Cleaner process. Must be DENIED
215 // if |found_uws| is false.
216 class ChromeCleanerRunnerTest
217 : public testing::TestWithParam<
218 std::tuple<UwsFoundState,
219 MockChromeCleanerProcess::CrashPoint,
220 PromptAcceptance>>,
221 public ChromeCleanerRunnerTestDelegate {
222 public:
223 void SetUp() override {
224 UwsFoundState uws_found_state;
225 MockChromeCleanerProcess::CrashPoint crash_point;
226 PromptAcceptance prompt_acceptance_to_send;
227 std::tie(uws_found_state, crash_point, prompt_acceptance_to_send) =
228 GetParam();
229
230 ASSERT_FALSE(uws_found_state == UwsFoundState::kNoUwsFound &&
231 prompt_acceptance_to_send != PromptAcceptance::DENIED);
232
233 cleaner_process_options_.SetDoFindUws(uws_found_state !=
234 UwsFoundState::kNoUwsFound);
235 cleaner_process_options_.set_reboot_required(
236 uws_found_state == UwsFoundState::kUwsFoundRebootRequired);
237 cleaner_process_options_.set_crash_point(crash_point);
238 prompt_acceptance_to_send_ = prompt_acceptance_to_send;
239
240 SetChromeCleanerRunnerTestDelegateForTesting(this);
241 scoped_feature_list_.InitAndEnableFeature(kInBrowserCleanerUIFeature);
242 }
243
244 void CallRunChromeCleaner() {
245 ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
246 base::FilePath(FILE_PATH_LITERAL("cleaner.exe")),
247 SwReporterInvocation(), ChromeMetricsStatus::kDisabled,
248 CleanerLogsStatus::kUploadDisabled,
249 base::BindOnce(&ChromeCleanerRunnerTest::OnPromptUser,
250 base::Unretained(this)),
251 base::BindOnce(&ChromeCleanerRunnerTest::OnConnectionClosed,
252 base::Unretained(this)),
253 base::BindOnce(&ChromeCleanerRunnerTest::OnProcessDone,
254 base::Unretained(this)),
255 base::ThreadTaskRunnerHandle::Get());
256 }
257
258 // ChromeCleanerRunnerTestDelegate overrides.
259
260 base::Process LaunchTestProcess(
261 const base::CommandLine& command_line,
262 const base::LaunchOptions& launch_options) override {
263 // Add switches and program name that the test process needs for the multi
264 // process tests.
265 base::CommandLine test_process_command_line =
266 base::GetMultiProcessTestChildBaseCommandLine();
267 for (const auto& pair : command_line.GetSwitches())
268 test_process_command_line.AppendSwitchNative(pair.first, pair.second);
269
270 cleaner_process_options_.AddSwitchesToCommandLine(
271 &test_process_command_line);
272
273 base::SpawnChildResult result = base::SpawnMultiProcessTestChild(
274 "MockChromeCleanerProcessMain", test_process_command_line,
275 launch_options);
276
277 EXPECT_TRUE(result.process.IsValid());
278 return std::move(result.process);
279 }
280
281 // IPC callbacks.
282
283 // Will receive the main Mojo message from the Mock Chrome Cleaner process.
284 void OnPromptUser(std::unique_ptr<std::set<base::FilePath>> files_to_delete,
285 ChromePrompt::PromptUserCallback response) {
286 on_prompt_user_called_ = true;
287 received_files_to_delete_ = std::move(files_to_delete);
288 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
289 ->PostTask(FROM_HERE, base::BindOnce(std::move(response),
290 prompt_acceptance_to_send_));
291 }
292
293 void QuitTestRunLoopIfCommunicationDone() {
294 if (on_process_done_called_ && on_connection_closed_called_)
295 run_loop_.QuitWhenIdle();
296 }
297
298 void OnConnectionClosed() {
299 on_connection_closed_called_ = true;
300 QuitTestRunLoopIfCommunicationDone();
301 }
302
303 void OnProcessDone(ChromeCleanerRunner::LaunchStatus launch_status) {
304 on_process_done_called_ = true;
305 launch_status_ = launch_status;
306 QuitTestRunLoopIfCommunicationDone();
307 }
308
309 protected:
310 content::TestBrowserThreadBundle test_browser_thread_bundle_;
311 base::test::ScopedFeatureList scoped_feature_list_;
312
313 base::RunLoop run_loop_;
314
315 MockChromeCleanerProcess::Options cleaner_process_options_;
316 PromptAcceptance prompt_acceptance_to_send_ = PromptAcceptance::UNSPECIFIED;
317
318 // Set by OnProcessDone().
319 ChromeCleanerRunner::LaunchStatus launch_status_ = {false, -1};
320 // Set by OnPromptUser().
321 std::unique_ptr<std::set<base::FilePath>> received_files_to_delete_;
322
323 bool on_prompt_user_called_ = false;
324 bool on_connection_closed_called_ = false;
325 bool on_process_done_called_ = false;
326 };
327
328 MULTIPROCESS_TEST_MAIN(MockChromeCleanerProcessMain) {
329 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
330 MockChromeCleanerProcess::Options options;
331 EXPECT_TRUE(MockChromeCleanerProcess::Options::FromCommandLine(*command_line,
332 &options));
333
334 std::string chrome_mojo_pipe_token = command_line->GetSwitchValueASCII(
335 chrome_cleaner::kChromeMojoPipeTokenSwitch);
336 EXPECT_FALSE(chrome_mojo_pipe_token.empty());
337
338 // Since failures in any of the above calls to EXPECT_*() do not actually fail
339 // the test, we need to ensure that we return an exit code to indicate test
340 // failure in such cases.
341 if (::testing::Test::HasFailure())
342 return MockChromeCleanerProcess::kInternalTestFailureExitCode;
343
344 MockChromeCleanerProcess mock_cleaner_process(options,
345 chrome_mojo_pipe_token);
346 return mock_cleaner_process.Run();
347 }
348
349 TEST_P(ChromeCleanerRunnerTest, WithMockCleanerProcess) {
350 CallRunChromeCleaner();
351 run_loop_.Run();
352
353 EXPECT_TRUE(on_process_done_called_);
354 EXPECT_TRUE(on_connection_closed_called_);
355 EXPECT_EQ(on_prompt_user_called_,
356 (cleaner_process_options_.crash_point() ==
357 MockChromeCleanerProcess::CrashPoint::kNone ||
358 cleaner_process_options_.crash_point() ==
359 MockChromeCleanerProcess::CrashPoint::kAfterResponseReceived));
360
361 if (on_prompt_user_called_ && !cleaner_process_options_.found_uws().empty()) {
362 EXPECT_EQ(*received_files_to_delete_,
363 cleaner_process_options_.files_to_delete());
364 }
365
366 EXPECT_TRUE(launch_status_.process_ok);
367 EXPECT_EQ(launch_status_.exit_code, cleaner_process_options_.ExpectedExitCode(
368 prompt_acceptance_to_send_));
369 }
370
371 INSTANTIATE_TEST_CASE_P(
372 All,
373 ChromeCleanerRunnerTest,
374 Combine(
375 Values(UwsFoundState::kNoUwsFound),
376 Values(MockChromeCleanerProcess::CrashPoint::kNone,
377 MockChromeCleanerProcess::CrashPoint::kOnStartup,
378 MockChromeCleanerProcess::CrashPoint::kAfterConnection,
379 MockChromeCleanerProcess::CrashPoint::kAfterRequestSent,
380 MockChromeCleanerProcess::CrashPoint::kAfterResponseReceived),
381 Values(PromptAcceptance::DENIED)));
382
383 INSTANTIATE_TEST_CASE_P(
384 UwsFound,
385 ChromeCleanerRunnerTest,
386 Combine(
387 Values(UwsFoundState::kUwsFoundRebootRequired,
388 UwsFoundState::kUwsFoundNoRebootRequired),
389 Values(MockChromeCleanerProcess::CrashPoint::kNone,
390 MockChromeCleanerProcess::CrashPoint::kOnStartup,
391 MockChromeCleanerProcess::CrashPoint::kAfterConnection,
392 MockChromeCleanerProcess::CrashPoint::kAfterRequestSent,
393 MockChromeCleanerProcess::CrashPoint::kAfterResponseReceived),
394 Values(PromptAcceptance::DENIED,
395 PromptAcceptance::ACCEPTED_WITH_LOGS,
396 PromptAcceptance::ACCEPTED_WITHOUT_LOGS)));
397
398 } // namespace
399 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698