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

Side by Side Diff: chrome/browser/safe_browsing/srt_fetcher_browsertest_win.cc

Issue 2834613003: Adds error handling support for the SwReporter launcher. (Closed)
Patch Set: Really? Created 3 years, 8 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" 5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h"
6 6
7 #include <initializer_list> 7 #include <initializer_list>
8 #include <set> 8 #include <set>
9 #include <tuple> 9 #include <tuple>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/callback.h" 15 #include "base/callback.h"
16 #include "base/callback_helpers.h" 16 #include "base/callback_helpers.h"
17 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
18 #include "base/macros.h"
18 #include "base/memory/ref_counted.h" 19 #include "base/memory/ref_counted.h"
19 #include "base/message_loop/message_loop.h" 20 #include "base/message_loop/message_loop.h"
20 #include "base/run_loop.h" 21 #include "base/run_loop.h"
21 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_number_conversions.h"
22 #include "base/test/multiprocess_test.h" 23 #include "base/test/multiprocess_test.h"
23 #include "base/test/scoped_feature_list.h" 24 #include "base/test/scoped_feature_list.h"
24 #include "base/test/test_mock_time_task_runner.h" 25 #include "base/test/test_mock_time_task_runner.h"
25 #include "base/threading/sequenced_task_runner_handle.h" 26 #include "base/threading/sequenced_task_runner_handle.h"
26 #include "base/threading/thread_task_runner_handle.h" 27 #include "base/threading/thread_task_runner_handle.h"
27 #include "base/time/time.h" 28 #include "base/time/time.h"
28 #include "base/version.h" 29 #include "base/version.h"
29 #include "chrome/browser/browser_process.h" 30 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/lifetime/keep_alive_types.h" 31 #include "chrome/browser/lifetime/keep_alive_types.h"
31 #include "chrome/browser/lifetime/scoped_keep_alive.h" 32 #include "chrome/browser/lifetime/scoped_keep_alive.h"
32 #include "chrome/browser/profiles/profile.h" 33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/safe_browsing/srt_chrome_prompt_impl.h"
33 #include "chrome/browser/safe_browsing/srt_client_info_win.h" 35 #include "chrome/browser/safe_browsing/srt_client_info_win.h"
34 #include "chrome/browser/ui/browser.h" 36 #include "chrome/browser/ui/browser.h"
35 #include "chrome/browser/ui/browser_finder.h" 37 #include "chrome/browser/ui/browser_finder.h"
36 #include "chrome/browser/ui/test/test_browser_dialog.h" 38 #include "chrome/browser/ui/test/test_browser_dialog.h"
37 #include "chrome/common/pref_names.h" 39 #include "chrome/common/pref_names.h"
38 #include "chrome/test/base/in_process_browser_test.h" 40 #include "chrome/test/base/in_process_browser_test.h"
39 #include "components/chrome_cleaner/public/constants/constants.h" 41 #include "components/chrome_cleaner/public/constants/constants.h"
40 #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h"
41 #include "components/component_updater/pref_names.h" 42 #include "components/component_updater/pref_names.h"
42 #include "components/prefs/pref_service.h" 43 #include "components/prefs/pref_service.h"
43 #include "components/safe_browsing_db/safe_browsing_prefs.h" 44 #include "components/safe_browsing_db/safe_browsing_prefs.h"
44 #include "mojo/edk/embedder/embedder.h" 45 #include "mojo/edk/embedder/embedder.h"
45 #include "mojo/edk/embedder/scoped_ipc_support.h" 46 #include "mojo/edk/embedder/scoped_ipc_support.h"
46 #include "mojo/edk/system/core.h" 47 #include "mojo/edk/system/core.h"
47 #include "testing/multiprocess_func_list.h" 48 #include "testing/multiprocess_func_list.h"
48 49
49 namespace safe_browsing { 50 namespace safe_browsing {
50 51
51 namespace { 52 namespace {
52 53
53 using chrome_cleaner::mojom::ElevationStatus; 54 using chrome_cleaner::mojom::ElevationStatus;
54 using chrome_cleaner::mojom::PromptAcceptance; 55 using chrome_cleaner::mojom::PromptAcceptance;
55 56
56 // Special switches passed by the parent process (test case) to the reporter 57 // Special switches passed by the parent process (test case) to the reporter
57 // child process to indicate the behavior that should be mocked. 58 // child process to indicate the behavior that should be mocked.
58 constexpr char kExitCodeToReturnSwitch[] = "exit-code-to-return"; 59 constexpr char kExitCodeToReturnSwitch[] = "exit-code-to-return";
59 constexpr char kReportUwSFoundSwitch[] = "report-uws-found"; 60 constexpr char kReportUwSFoundSwitch[] = "report-uws-found";
60 constexpr char kReportElevationRequiredSwitch[] = "report-elevation-required"; 61 constexpr char kReportElevationRequiredSwitch[] = "report-elevation-required";
61 constexpr char kExpectedPromptAcceptanceSwitch[] = "expected-prompt-acceptance"; 62 constexpr char kExpectedPromptAcceptanceSwitch[] = "expected-prompt-acceptance";
63 constexpr char kExpectedReporterFailureSwitch[] = "expected-reporter-crash";
62 64
63 // The exit code to be returned in case of failure in the child process. 65 // The exit code to be returned in case of failure in the child process.
64 // This should never be passed as the expected exit code to be reported by 66 // This should never be passed as the expected exit code to be reported by
65 // tests. 67 // tests.
66 constexpr int kFailureExitCode = -1; 68 constexpr int kFailureExitCode = -1;
67 69
68 // Pass the |prompt_acceptance| to the mock child process in command line 70 // Pass the |prompt_acceptance| to the mock child process in command line
69 // switch kExpectedPromptAcceptanceSwitch. 71 // switch kExpectedPromptAcceptanceSwitch.
70 void AddPromptAcceptanceToCommandLine(PromptAcceptance prompt_acceptance, 72 void AddPromptAcceptanceToCommandLine(PromptAcceptance prompt_acceptance,
71 base::CommandLine* command_line) { 73 base::CommandLine* command_line) {
(...skipping 16 matching lines...) Expand all
88 if (chrome_cleaner::mojom::IsKnownEnumValue(prompt_acceptance)) 90 if (chrome_cleaner::mojom::IsKnownEnumValue(prompt_acceptance))
89 return prompt_acceptance; 91 return prompt_acceptance;
90 } 92 }
91 return PromptAcceptance::UNSPECIFIED; 93 return PromptAcceptance::UNSPECIFIED;
92 } 94 }
93 95
94 // Pointer to ChromePromptPtr object to be used by the child process. The 96 // Pointer to ChromePromptPtr object to be used by the child process. The
95 // object must be created, deleted, and accessed on the IPC thread only. 97 // object must be created, deleted, and accessed on the IPC thread only.
96 chrome_cleaner::mojom::ChromePromptPtr* g_chrome_prompt_ptr = nullptr; 98 chrome_cleaner::mojom::ChromePromptPtr* g_chrome_prompt_ptr = nullptr;
97 99
100 // Potential failures in the reporter process that should be handled by the
101 // parent process.
102 enum class MockedReporterFailure {
103 kNone = 0,
104 // Crashes at specific moments in the reporter when connected to the IPC.
105 kCrashOnStartup = 1,
106 kCrashAfterConnectedToParentProcess = 2,
107 kCrashWhileWaitingForResponse = 3,
108 kCrashAfterReceivedResponse = 4,
109 // Once an IPC message is sent by the reporter, the parent process will
110 // report a bad message that will lead to an invocation of OnConnectionError.
111 kBadMessageReported = 5,
112 };
113
114 void AddExpectedCrashToCommandLine(MockedReporterFailure reporter_failure,
115 base::CommandLine* command_line) {
116 command_line->AppendSwitchASCII(
117 kExpectedReporterFailureSwitch,
118 base::IntToString(static_cast<int>(reporter_failure)));
119 }
120
121 void CrashIf(MockedReporterFailure reporter_failure) {
122 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
123 const std::string& expected_str =
124 command_line->GetSwitchValueASCII(kExpectedReporterFailureSwitch);
125 int val = -1;
126 if (base::StringToInt(expected_str, &val) &&
127 static_cast<MockedReporterFailure>(val) == reporter_failure) {
128 exit(kFailureExitCode);
129 }
130 }
131
98 // The callback function to be passed to ChromePrompt::PromptUser to check if 132 // The callback function to be passed to ChromePrompt::PromptUser to check if
99 // the prompt accepted returned by the parent process is equal to 133 // the prompt accepted returned by the parent process is equal to
100 // |expected_prompt_acceptance|. Will set |expected_value_received| with the 134 // |expected_prompt_acceptance|. Will set |expected_value_received| with the
101 // comparison result, so that the main thread can report failure. Will invoke 135 // comparison result, so that the main thread can report failure. Will invoke
102 // |done| callback when done. 136 // |done| callback when done.
103 void PromptUserCallback(const base::Closure& done, 137 void PromptUserCallback(const base::Closure& done,
104 PromptAcceptance expected_prompt_acceptance, 138 PromptAcceptance expected_prompt_acceptance,
105 bool* expected_value_received, 139 bool* expected_value_received,
106 PromptAcceptance prompt_acceptance) { 140 PromptAcceptance prompt_acceptance) {
107 *expected_value_received = prompt_acceptance == expected_prompt_acceptance; 141 *expected_value_received = prompt_acceptance == expected_prompt_acceptance;
108 // It's safe to delete the ChromePromptPtr object here, since it will not be 142 // It's safe to delete the ChromePromptPtr object here, since it will not be
109 // used anymore by the child process. 143 // used anymore by the child process.
110 delete g_chrome_prompt_ptr; 144 delete g_chrome_prompt_ptr;
111 g_chrome_prompt_ptr = nullptr; 145 g_chrome_prompt_ptr = nullptr;
146 CrashIf(MockedReporterFailure::kCrashAfterReceivedResponse);
112 done.Run(); 147 done.Run();
113 } 148 }
114 149
115 // Mocks the sending of scan results from the child process to the parent 150 // Mocks the sending of scan results from the child process to the parent
116 // process. Obtains the behavior to be mocked from special switches in 151 // process. Obtains the behavior to be mocked from special switches in
117 // |command_line|. Sets |expected_value_received| as true if the parent 152 // |command_line|. Sets |expected_value_received| as true if the parent
118 // process replies with the expected prompt acceptance value. 153 // process replies with the expected prompt acceptance value.
119 void SendScanResults(const std::string& chrome_mojo_pipe_token, 154 void SendScanResults(const std::string& chrome_mojo_pipe_token,
120 const base::CommandLine& command_line, 155 const base::CommandLine& command_line,
121 const base::Closure& done, 156 const base::Closure& done,
(...skipping 16 matching lines...) Expand all
138 uws->observed_behaviours = chrome_cleaner::mojom::ObservedBehaviours::New(); 173 uws->observed_behaviours = chrome_cleaner::mojom::ObservedBehaviours::New();
139 removable_uws_found.push_back(std::move(uws)); 174 removable_uws_found.push_back(std::move(uws));
140 } 175 }
141 const ElevationStatus elevation_status = 176 const ElevationStatus elevation_status =
142 command_line.HasSwitch(kReportElevationRequiredSwitch) 177 command_line.HasSwitch(kReportElevationRequiredSwitch)
143 ? ElevationStatus::REQUIRED 178 ? ElevationStatus::REQUIRED
144 : ElevationStatus::NOT_REQUIRED; 179 : ElevationStatus::NOT_REQUIRED;
145 const PromptAcceptance expected_prompt_acceptance = 180 const PromptAcceptance expected_prompt_acceptance =
146 PromptAcceptanceFromCommandLine(command_line); 181 PromptAcceptanceFromCommandLine(command_line);
147 182
183 // This task is posted to the IPC thread so that it will happen after the
184 // request is sent to the parent process and before the response gets
185 // handled on the IPC thread.
186 base::SequencedTaskRunnerHandle::Get()->PostTask(
187 FROM_HERE,
188 base::Bind(&CrashIf,
189 MockedReporterFailure::kCrashWhileWaitingForResponse));
190
148 (*g_chrome_prompt_ptr) 191 (*g_chrome_prompt_ptr)
149 ->PromptUser( 192 ->PromptUser(
150 std::move(removable_uws_found), elevation_status, 193 std::move(removable_uws_found), elevation_status,
151 base::Bind(&PromptUserCallback, done, expected_prompt_acceptance, 194 base::Bind(&PromptUserCallback, done, expected_prompt_acceptance,
152 expected_value_received)); 195 expected_value_received));
153 } 196 }
154 197
155 // Connects to the parent process and sends mocked scan results. Returns true 198 // Connects to the parent process and sends mocked scan results. Returns true
156 // if connection was successful and the prompt acceptance results sent by the 199 // if connection was successful and the prompt acceptance results sent by the
157 // parent process are the same as expected. 200 // parent process are the same as expected.
158 bool ConnectAndSendDataToParentProcess( 201 bool ConnectAndSendDataToParentProcess(
159 const std::string& chrome_mojo_pipe_token, 202 const std::string& chrome_mojo_pipe_token,
160 const base::CommandLine& command_line) { 203 const base::CommandLine& command_line) {
161 DCHECK(!chrome_mojo_pipe_token.empty()); 204 DCHECK(!chrome_mojo_pipe_token.empty());
162 205
163 mojo::edk::Init(); 206 mojo::edk::Init();
164 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); 207 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
165 base::Thread io_thread("IPCThread"); 208 base::Thread io_thread("IPCThread");
166 if (!io_thread.StartWithOptions(options)) 209 if (!io_thread.StartWithOptions(options))
167 return false; 210 return false;
168 mojo::edk::ScopedIPCSupport ipc_support( 211 mojo::edk::ScopedIPCSupport ipc_support(
169 io_thread.task_runner(), 212 io_thread.task_runner(),
170 mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); 213 mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
171 mojo::edk::SetParentPipeHandleFromCommandLine(); 214 mojo::edk::SetParentPipeHandleFromCommandLine();
215
216 CrashIf(MockedReporterFailure::kCrashAfterConnectedToParentProcess);
217
172 base::MessageLoop message_loop; 218 base::MessageLoop message_loop;
173 base::RunLoop run_loop; 219 base::RunLoop run_loop;
174 // After the response from the parent process is received, this will post a 220 // After the response from the parent process is received, this will post a
175 // task to unblock the child process's main thread. 221 // task to unblock the child process's main thread.
176 auto done = base::Bind( 222 auto done = base::Bind(
177 [](scoped_refptr<base::SequencedTaskRunner> main_runner, 223 [](scoped_refptr<base::SequencedTaskRunner> main_runner,
178 base::Closure quit_closure) { 224 base::Closure quit_closure) {
179 main_runner->PostTask(FROM_HERE, std::move(quit_closure)); 225 main_runner->PostTask(FROM_HERE, std::move(quit_closure));
180 }, 226 },
181 base::SequencedTaskRunnerHandle::Get(), 227 base::SequencedTaskRunnerHandle::Get(),
182 base::Passed(run_loop.QuitClosure())); 228 base::Passed(run_loop.QuitClosure()));
183 229
184 bool expected_value_received = false; 230 bool expected_value_received = false;
185 io_thread.task_runner()->PostTask( 231 io_thread.task_runner()->PostTask(
186 FROM_HERE, base::Bind(&SendScanResults, chrome_mojo_pipe_token, 232 FROM_HERE, base::Bind(&SendScanResults, chrome_mojo_pipe_token,
187 command_line, done, &expected_value_received)); 233 command_line, done, &expected_value_received));
234
188 run_loop.Run(); 235 run_loop.Run();
189 236
190 return expected_value_received; 237 return expected_value_received;
191 } 238 }
192 239
193 // Mocks a Software Reporter process that returns an exit code specified by 240 // Mocks a Software Reporter process that returns an exit code specified by
194 // command line switch kExitCodeToReturnSwitch. If a Mojo IPC is available, 241 // command line switch kExitCodeToReturnSwitch. If a Mojo IPC is available,
195 // this will also connect to the parent process and send mocked scan results 242 // this will also connect to the parent process and send mocked scan results
196 // to the parent process using data passed as command line switches. 243 // to the parent process using data passed as command line switches.
197 MULTIPROCESS_TEST_MAIN(MockSwReporterProcess) { 244 MULTIPROCESS_TEST_MAIN(MockSwReporterProcess) {
198 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 245 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
246 CrashIf(MockedReporterFailure::kCrashOnStartup);
199 const std::string& str = 247 const std::string& str =
200 command_line->GetSwitchValueASCII(kExitCodeToReturnSwitch); 248 command_line->GetSwitchValueASCII(kExitCodeToReturnSwitch);
201 const std::string& chrome_mojo_pipe_token = command_line->GetSwitchValueASCII( 249 const std::string& chrome_mojo_pipe_token = command_line->GetSwitchValueASCII(
202 chrome_cleaner::kChromeMojoPipeTokenSwitch); 250 chrome_cleaner::kChromeMojoPipeTokenSwitch);
203 int exit_code_to_report = kFailureExitCode; 251 int exit_code_to_report = kFailureExitCode;
204 bool success = base::StringToInt(str, &exit_code_to_report) && 252 bool success = base::StringToInt(str, &exit_code_to_report) &&
205 (chrome_mojo_pipe_token.empty() || 253 (chrome_mojo_pipe_token.empty() ||
206 ConnectAndSendDataToParentProcess(chrome_mojo_pipe_token, 254 ConnectAndSendDataToParentProcess(chrome_mojo_pipe_token,
207 *command_line)); 255 *command_line));
208 return success ? exit_code_to_report : kFailureExitCode; 256 return success ? exit_code_to_report : kFailureExitCode;
209 } 257 }
210 258
259 // Decorates a ChromePromptImpl object to simulate failures indentified by the
260 // parent process and keeps track of errors handled. By default, delegates all
261 // actions to the decorated object.
262 class ReportBadMessageChromePromptImpl : public ChromePromptImpl {
263 public:
264 ReportBadMessageChromePromptImpl(
265 chrome_cleaner::mojom::ChromePromptRequest request,
266 bool bad_message_expected,
267 base::Closure on_connection_closed)
268 : ChromePromptImpl(std::move(request), std::move(on_connection_closed)),
269 bad_message_expected_(bad_message_expected) {}
270 ~ReportBadMessageChromePromptImpl() override = default;
271
272 void PromptUser(
273 std::vector<chrome_cleaner::mojom::UwSPtr> removable_uws_found,
274 chrome_cleaner::mojom::ElevationStatus elevation_status,
275 const chrome_cleaner::mojom::ChromePrompt::PromptUserCallback& callback)
276 override {
277 if (bad_message_expected_)
278 mojo::ReportBadMessage("bad message");
279
280 ChromePromptImpl::PromptUser(std::move(removable_uws_found),
281 elevation_status, callback);
282 }
283
284 private:
285 bool bad_message_expected_ = false;
286
287 DISALLOW_COPY_AND_ASSIGN(ReportBadMessageChromePromptImpl);
288 };
289
211 // Parameters for this test: 290 // Parameters for this test:
212 // - bool in_browser_cleaner_ui: indicates if InBrowserCleanerUI experiment 291 // - bool in_browser_cleaner_ui: indicates if InBrowserCleanerUI experiment
213 // is enabled; if so, the parent and the child processes will communicate 292 // is enabled; if so, the parent and the child processes will communicate
214 // via a Mojo IPC; 293 // via a Mojo IPC.
215 // - ElevationStatus elevation_status: indicates if the scan results sent by 294 // - ElevationStatus elevation_status: indicates if the scan results sent by
216 // the child process should consider that elevation will be required for 295 // the child process should consider that elevation will be required for
217 // cleanup. 296 // cleanup.
297 // - MockedReporterFailure expected_reporter_failure: indicates errors that
298 // should be simulated in the reporter process.
218 class SRTFetcherTest 299 class SRTFetcherTest
219 : public InProcessBrowserTest, 300 : public InProcessBrowserTest,
220 public SwReporterTestingDelegate, 301 public SwReporterTestingDelegate,
221 public ::testing::WithParamInterface<std::tuple<bool, ElevationStatus>> { 302 public ::testing::WithParamInterface<
303 std::tuple<bool, ElevationStatus, MockedReporterFailure>> {
222 public: 304 public:
305 SRTFetcherTest() = default;
306
223 void SetUpInProcessBrowserTestFixture() override { 307 void SetUpInProcessBrowserTestFixture() override {
224 SetSwReporterTestingDelegate(this); 308 SetSwReporterTestingDelegate(this);
225 309
226 std::tie(in_browser_cleaner_ui_, elevation_status_) = GetParam(); 310 std::tie(in_browser_cleaner_ui_, elevation_status_,
311 expected_reporter_failure_) = GetParam();
227 // The config should only accept elevation_status_ if InBrowserCleanerUI 312 // The config should only accept elevation_status_ if InBrowserCleanerUI
228 // feature is enabled. 313 // feature is enabled.
229 ASSERT_TRUE(elevation_status_ == ElevationStatus::NOT_REQUIRED || 314 ASSERT_TRUE(elevation_status_ == ElevationStatus::NOT_REQUIRED ||
230 in_browser_cleaner_ui_); 315 in_browser_cleaner_ui_);
231 316
232 if (in_browser_cleaner_ui_) 317 if (in_browser_cleaner_ui_)
233 scoped_feature_list_.InitAndEnableFeature(kInBrowserCleanerUIFeature); 318 scoped_feature_list_.InitAndEnableFeature(kInBrowserCleanerUIFeature);
234 else 319 else
235 scoped_feature_list_.InitAndDisableFeature(kInBrowserCleanerUIFeature); 320 scoped_feature_list_.InitAndDisableFeature(kInBrowserCleanerUIFeature);
236 } 321 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 // process. 358 // process.
274 // Records the launch and parameters used for further verification. 359 // Records the launch and parameters used for further verification.
275 base::Process LaunchReporter( 360 base::Process LaunchReporter(
276 const SwReporterInvocation& invocation, 361 const SwReporterInvocation& invocation,
277 const base::LaunchOptions& launch_options) override { 362 const base::LaunchOptions& launch_options) override {
278 ++reporter_launch_count_; 363 ++reporter_launch_count_;
279 reporter_launch_parameters_.push_back(invocation); 364 reporter_launch_parameters_.push_back(invocation);
280 if (first_launch_callback_) 365 if (first_launch_callback_)
281 std::move(first_launch_callback_).Run(); 366 std::move(first_launch_callback_).Run();
282 367
368 if (exit_code_to_report_ == kReporterNotLaunchedExitCode)
369 return base::Process(); // IsValid() will return false.
370
283 base::CommandLine command_line( 371 base::CommandLine command_line(
284 base::GetMultiProcessTestChildBaseCommandLine()); 372 base::GetMultiProcessTestChildBaseCommandLine());
285 command_line.AppendArguments(invocation.command_line, 373 command_line.AppendArguments(invocation.command_line,
286 /*include_program=*/false); 374 /*include_program=*/false);
287 command_line.AppendSwitchASCII(kExitCodeToReturnSwitch, 375 command_line.AppendSwitchASCII(kExitCodeToReturnSwitch,
288 base::IntToString(exit_code_to_report_)); 376 base::IntToString(exit_code_to_report_));
377
289 if (in_browser_cleaner_ui_) { 378 if (in_browser_cleaner_ui_) {
290 AddPromptAcceptanceToCommandLine(PromptAcceptance::DENIED, &command_line); 379 AddPromptAcceptanceToCommandLine(PromptAcceptance::DENIED, &command_line);
291 if (exit_code_to_report_ == chrome_cleaner::kSwReporterCleanupNeeded) { 380 if (exit_code_to_report_ == chrome_cleaner::kSwReporterCleanupNeeded) {
292 command_line.AppendSwitch(kReportUwSFoundSwitch); 381 command_line.AppendSwitch(kReportUwSFoundSwitch);
293 if (elevation_status_ == ElevationStatus::REQUIRED) 382 if (elevation_status_ == ElevationStatus::REQUIRED)
294 command_line.AppendSwitch(kReportElevationRequiredSwitch); 383 command_line.AppendSwitch(kReportElevationRequiredSwitch);
295 } 384 }
296 } 385 }
386
387 if (expected_reporter_failure_ != MockedReporterFailure::kNone)
388 AddExpectedCrashToCommandLine(expected_reporter_failure_, &command_line);
389
390 bad_message_expected_ = expected_reporter_failure_ ==
391 MockedReporterFailure::kBadMessageReported;
392 bad_message_reported_ = false;
393
297 base::SpawnChildResult result = base::SpawnMultiProcessTestChild( 394 base::SpawnChildResult result = base::SpawnMultiProcessTestChild(
298 "MockSwReporterProcess", command_line, launch_options); 395 "MockSwReporterProcess", command_line, launch_options);
299 return std::move(result.process); 396 return std::move(result.process);
300 } 397 }
301 398
302 // Returns the test's idea of the current time. 399 // Returns the test's idea of the current time.
303 base::Time Now() const override { return mock_time_task_runner_->Now(); } 400 base::Time Now() const override { return mock_time_task_runner_->Now(); }
304 401
305 // Returns a task runner to use when launching the reporter (which is 402 // Returns a task runner to use when launching the reporter (which is
306 // normally a blocking action). 403 // normally a blocking action).
307 base::TaskRunner* BlockingTaskRunner() const override { 404 base::TaskRunner* BlockingTaskRunner() const override {
308 // Use the test's main task runner so that we don't need to pump another 405 // Use the test's main task runner so that we don't need to pump another
309 // message loop. Since the test calls LaunchReporter instead of actually 406 // message loop. Since the test calls LaunchReporter instead of actually
310 // doing a blocking reporter launch, it doesn't matter that the task runner 407 // doing a blocking reporter launch, it doesn't matter that the task runner
311 // doesn't have the MayBlock trait. 408 // doesn't have the MayBlock trait.
312 return mock_time_task_runner_.get(); 409 return mock_time_task_runner_.get();
313 } 410 }
314 411
412 std::unique_ptr<ChromePromptImpl> CreateChromePromptImpl(
413 chrome_cleaner::mojom::ChromePromptRequest request) override {
414 return base::MakeUnique<ReportBadMessageChromePromptImpl>(
415 std::move(request), bad_message_expected_,
416 base::Bind(&SRTFetcherTest::OnConnectionClosed,
417 base::Unretained(this)));
418 }
419
420 void OnConnectionClosed() override {}
421
422 void OnConnectionError(const std::string& message) override {
423 bad_message_reported_ = true;
424 }
425
315 // Schedules a single reporter to run. 426 // Schedules a single reporter to run.
316 void RunReporter(int exit_code_to_report, 427 void RunReporter(int exit_code_to_report,
317 const base::FilePath& exe_path = base::FilePath()) { 428 const base::FilePath& exe_path = base::FilePath()) {
318 exit_code_to_report_ = exit_code_to_report; 429 exit_code_to_report_ = exit_code_to_report;
319 auto invocation = SwReporterInvocation::FromFilePath(exe_path); 430 auto invocation = SwReporterInvocation::FromFilePath(exe_path);
320 invocation.supported_behaviours = 431 invocation.supported_behaviours =
321 SwReporterInvocation::BEHAVIOUR_LOG_EXIT_CODE_TO_PREFS | 432 SwReporterInvocation::BEHAVIOUR_LOG_EXIT_CODE_TO_PREFS |
322 SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT | 433 SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT |
323 SwReporterInvocation::BEHAVIOUR_ALLOW_SEND_REPORTER_LOGS; 434 SwReporterInvocation::BEHAVIOUR_ALLOW_SEND_REPORTER_LOGS;
324 435
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 bool expect_prompt) { 504 bool expect_prompt) {
394 EXPECT_TRUE(mock_time_task_runner_->HasPendingTask()); 505 EXPECT_TRUE(mock_time_task_runner_->HasPendingTask());
395 reporter_launch_count_ = 0; 506 reporter_launch_count_ = 0;
396 reporter_launch_parameters_.clear(); 507 reporter_launch_parameters_.clear();
397 prompt_trigger_called_ = false; 508 prompt_trigger_called_ = false;
398 509
399 mock_time_task_runner_->FastForwardBy( 510 mock_time_task_runner_->FastForwardBy(
400 base::TimeDelta::FromDays(days_until_launch)); 511 base::TimeDelta::FromDays(days_until_launch));
401 512
402 EXPECT_EQ(expected_launch_count, reporter_launch_count_); 513 EXPECT_EQ(expected_launch_count, reporter_launch_count_);
403 EXPECT_EQ(expect_prompt, prompt_trigger_called_); 514 // Note: a bad message error will not prevent the prompt that is shown to
515 // the user today. Once we hook the new prompt here, we will need to review
516 // this expectation.
517 EXPECT_EQ(expect_prompt &&
518 (expected_reporter_failure_ == MockedReporterFailure::kNone ||
519 expected_reporter_failure_ ==
520 MockedReporterFailure::kBadMessageReported),
521 prompt_trigger_called_);
522
523 EXPECT_EQ(bad_message_expected_, bad_message_reported_);
404 } 524 }
405 525
406 // Expects that after |days_until_launched| days, the reporter will be 526 // Expects that after |days_until_launched| days, the reporter will be
407 // launched once with each path in |expected_launch_paths|, and TriggerPrompt 527 // launched once with each path in |expected_launch_paths|, and TriggerPrompt
408 // will be called if and only if |expect_prompt| is true. 528 // will be called if and only if |expect_prompt| is true.
409 void ExpectReporterLaunches( 529 void ExpectReporterLaunches(
410 int days_until_launch, 530 int days_until_launch,
411 const std::vector<base::FilePath>& expected_launch_paths, 531 const std::vector<base::FilePath>& expected_launch_paths,
412 bool expect_prompt) { 532 bool expect_prompt) {
413 ExpectReporterLaunches(days_until_launch, expected_launch_paths.size(), 533 ExpectReporterLaunches(days_until_launch, expected_launch_paths.size(),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 580
461 // A task runner with a mock clock. 581 // A task runner with a mock clock.
462 scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_ = 582 scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_ =
463 new base::TestMockTimeTaskRunner(); 583 new base::TestMockTimeTaskRunner();
464 584
465 // The task runner that was in use before installing |mock_time_task_runner_|. 585 // The task runner that was in use before installing |mock_time_task_runner_|.
466 scoped_refptr<base::SingleThreadTaskRunner> saved_task_runner_; 586 scoped_refptr<base::SingleThreadTaskRunner> saved_task_runner_;
467 587
468 bool in_browser_cleaner_ui_; 588 bool in_browser_cleaner_ui_;
469 ElevationStatus elevation_status_; 589 ElevationStatus elevation_status_;
590 MockedReporterFailure expected_reporter_failure_;
591
592 // Indicates if a bad message error should be simulated by the parent
593 // process.
594 bool bad_message_expected_;
595
596 // Set by ReportBadMessageChromePromptImpl if a bad message error is reported.
597 bool bad_message_reported_;
470 598
471 bool prompt_trigger_called_ = false; 599 bool prompt_trigger_called_ = false;
472 int reporter_launch_count_ = 0; 600 int reporter_launch_count_ = 0;
473 std::vector<SwReporterInvocation> reporter_launch_parameters_; 601 std::vector<SwReporterInvocation> reporter_launch_parameters_;
474 int exit_code_to_report_ = kReporterFailureExitCode; 602 int exit_code_to_report_ = kReporterNotLaunchedExitCode;
475 603
476 // A callback to invoke when the first reporter of a queue is launched. This 604 // A callback to invoke when the first reporter of a queue is launched. This
477 // can be used to perform actions in the middle of a queue of reporters which 605 // can be used to perform actions in the middle of a queue of reporters which
478 // all launch on the same mock clock tick. 606 // all launch on the same mock clock tick.
479 base::OnceClosure first_launch_callback_; 607 base::OnceClosure first_launch_callback_;
480 608
481 base::test::ScopedFeatureList scoped_feature_list_; 609 base::test::ScopedFeatureList scoped_feature_list_;
610
611 DISALLOW_COPY_AND_ASSIGN(SRTFetcherTest);
482 }; 612 };
483 613
484 class SRTFetcherPromptTest : public DialogBrowserTest { 614 class SRTFetcherPromptTest : public DialogBrowserTest {
485 public: 615 public:
486 void ShowDialog(const std::string& name) override { 616 void ShowDialog(const std::string& name) override {
487 if (name == "SRTErrorNoFile") 617 if (name == "SRTErrorNoFile")
488 DisplaySRTPromptForTesting(base::FilePath()); 618 DisplaySRTPromptForTesting(base::FilePath());
489 else if (name == "SRTErrorFile") 619 else if (name == "SRTErrorFile")
490 DisplaySRTPromptForTesting( 620 DisplaySRTPromptForTesting(
491 base::FilePath().Append(FILE_PATH_LITERAL("c:\temp\testfile.txt"))); 621 base::FilePath().Append(FILE_PATH_LITERAL("c:\temp\testfile.txt")));
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 mock_time_task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(10)); 683 mock_time_task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(10));
554 684
555 // On opening the new browser, the prompt should be shown and the reporter 685 // On opening the new browser, the prompt should be shown and the reporter
556 // should be scheduled to run later. 686 // should be scheduled to run later.
557 EXPECT_EQ(1, reporter_launch_count_); 687 EXPECT_EQ(1, reporter_launch_count_);
558 EXPECT_TRUE(prompt_trigger_called_); 688 EXPECT_TRUE(prompt_trigger_called_);
559 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns); 689 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns);
560 } 690 }
561 691
562 IN_PROC_BROWSER_TEST_P(SRTFetcherTest, Failure) { 692 IN_PROC_BROWSER_TEST_P(SRTFetcherTest, Failure) {
563 RunReporter(kReporterFailureExitCode); 693 RunReporter(kReporterNotLaunchedExitCode);
564 ExpectReporterLaunches(0, 1, false); 694 ExpectReporterLaunches(0, 1, false);
565 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns); 695 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns);
566 } 696 }
567 697
568 IN_PROC_BROWSER_TEST_P(SRTFetcherTest, RunDaily) { 698 IN_PROC_BROWSER_TEST_P(SRTFetcherTest, RunDaily) {
569 PrefService* local_state = g_browser_process->local_state(); 699 PrefService* local_state = g_browser_process->local_state();
570 local_state->SetBoolean(prefs::kSwReporterPendingPrompt, true); 700 local_state->SetBoolean(prefs::kSwReporterPendingPrompt, true);
571 SetDaysSinceLastTriggered(kDaysBetweenSuccessfulSwReporterRuns - 1); 701 SetDaysSinceLastTriggered(kDaysBetweenSuccessfulSwReporterRuns - 1);
572 ASSERT_GT(kDaysBetweenSuccessfulSwReporterRuns - 1, 702 ASSERT_GT(kDaysBetweenSuccessfulSwReporterRuns - 1,
573 kDaysBetweenSwReporterRunsForPendingPrompt); 703 kDaysBetweenSwReporterRunsForPendingPrompt);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 826
697 // Time passes... Now the 3-element queue should run. 827 // Time passes... Now the 3-element queue should run.
698 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns, 828 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns,
699 {path1, path2, path3}, false); 829 {path1, path2, path3}, false);
700 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns); 830 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns);
701 } 831 }
702 832
703 // Second launch should not occur after a failure. 833 // Second launch should not occur after a failure.
704 { 834 {
705 SCOPED_TRACE("Launch multiple times with failure"); 835 SCOPED_TRACE("Launch multiple times with failure");
706 RunReporterQueue(kReporterFailureExitCode, invocations); 836 RunReporterQueue(kReporterNotLaunchedExitCode, invocations);
707 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns, {path1}, 837 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns, {path1},
708 false); 838 false);
709 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns); 839 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns);
710 840
711 // If we try again before the reporting period is up, it should not do 841 // If we try again before the reporting period is up, it should not do
712 // anything. 842 // anything.
713 ExpectReporterLaunches(0, {}, false); 843 ExpectReporterLaunches(0, {}, false);
714 844
715 // After enough time has passed, should try the queue again. 845 // After enough time has passed, should try the queue again.
716 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns, {path1}, 846 ExpectReporterLaunches(kDaysBetweenSuccessfulSwReporterRuns, {path1},
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 ExpectLoggingSwitches(reporter_launch_parameters_[1], true); 928 ExpectLoggingSwitches(reporter_launch_parameters_[1], true);
799 ExpectLastReportSentInTheLastHour(); 929 ExpectLastReportSentInTheLastHour();
800 } 930 }
801 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns); 931 ExpectToRunAgain(kDaysBetweenSuccessfulSwReporterRuns);
802 } 932 }
803 933
804 INSTANTIATE_TEST_CASE_P( 934 INSTANTIATE_TEST_CASE_P(
805 NoInBrowserCleanerUI, 935 NoInBrowserCleanerUI,
806 SRTFetcherTest, 936 SRTFetcherTest,
807 testing::Combine(testing::Values(false), 937 testing::Combine(testing::Values(false),
808 testing::Values(ElevationStatus::NOT_REQUIRED))); 938 testing::Values(ElevationStatus::NOT_REQUIRED),
939 testing::Values(MockedReporterFailure::kNone,
940 MockedReporterFailure::kCrashOnStartup)));
809 941
810 INSTANTIATE_TEST_CASE_P( 942 INSTANTIATE_TEST_CASE_P(
811 InBrowserCleanerUI, 943 InBrowserCleanerUI,
812 SRTFetcherTest, 944 SRTFetcherTest,
813 testing::Combine(testing::Values(true), 945 testing::Combine(
814 testing::Values(ElevationStatus::NOT_REQUIRED, 946 testing::Values(true),
815 ElevationStatus::REQUIRED))); 947 testing::Values(ElevationStatus::NOT_REQUIRED,
948 ElevationStatus::REQUIRED),
949 testing::Values(
950 MockedReporterFailure::kNone,
951 MockedReporterFailure::kCrashOnStartup,
952 MockedReporterFailure::kCrashAfterConnectedToParentProcess,
953 MockedReporterFailure::kCrashWhileWaitingForResponse,
954 MockedReporterFailure::kCrashAfterReceivedResponse,
955 MockedReporterFailure::kBadMessageReported)));
816 956
817 // This provide tests which allows explicit invocation of the SRT Prompt 957 // This provide tests which allows explicit invocation of the SRT Prompt
818 // useful for checking dialog layout or any other interactive functionality 958 // useful for checking dialog layout or any other interactive functionality
819 // tests. See docs/testing/test_browser_dialog.md for description of the 959 // tests. See docs/testing/test_browser_dialog.md for description of the
820 // testing framework. 960 // testing framework.
821 IN_PROC_BROWSER_TEST_F(SRTFetcherPromptTest, InvokeDialog_SRTErrorNoFile) { 961 IN_PROC_BROWSER_TEST_F(SRTFetcherPromptTest, InvokeDialog_SRTErrorNoFile) {
822 RunDialog(); 962 RunDialog();
823 } 963 }
824 964
825 IN_PROC_BROWSER_TEST_F(SRTFetcherPromptTest, InvokeDialog_SRTErrorFile) { 965 IN_PROC_BROWSER_TEST_F(SRTFetcherPromptTest, InvokeDialog_SRTErrorFile) {
826 RunDialog(); 966 RunDialog();
827 } 967 }
828 968
829 } // namespace safe_browsing 969 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/srt_chrome_prompt_impl.cc ('k') | chrome/browser/safe_browsing/srt_fetcher_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698