| Index: chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
|
| diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ce4ed9d4d5c3be7297915c060fdb5251d989be34
|
| --- /dev/null
|
| +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
|
| @@ -0,0 +1,243 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h"
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/base_paths.h"
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/feature_list.h"
|
| +#include "base/location.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/path_service.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/task_scheduler/post_task.h"
|
| +#include "chrome/browser/safe_browsing/chrome_cleaner/srt_client_info_win.h"
|
| +#include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
|
| +#include "chrome/installer/util/install_util.h"
|
| +#include "components/chrome_cleaner/public/constants/constants.h"
|
| +#include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h"
|
| +#include "components/version_info/version_info.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "mojo/edk/embedder/connection_params.h"
|
| +#include "mojo/edk/embedder/embedder.h"
|
| +#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
|
| +#include "mojo/edk/embedder/platform_channel_pair.h"
|
| +#include "mojo/edk/embedder/transport_protocol.h"
|
| +#include "mojo/public/cpp/system/message_pipe.h"
|
| +
|
| +using chrome_cleaner::mojom::ChromePrompt;
|
| +using chrome_cleaner::mojom::ChromePromptRequest;
|
| +using content::BrowserThread;
|
| +
|
| +namespace safe_browsing {
|
| +
|
| +namespace {
|
| +
|
| +// Global delegate used to override the launching of the Cleaner process during
|
| +// tests.
|
| +ChromeCleanerRunnerTestDelegate* g_test_delegate = nullptr;
|
| +
|
| +void ReleaseChromePromptImpl(
|
| + std::unique_ptr<ChromePromptImpl> chrome_prompt_impl) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK(chrome_prompt_impl);
|
| + chrome_prompt_impl.reset();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +void ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
|
| + const base::FilePath& cleaner_executable_path,
|
| + const SwReporterInvocation& reporter_invocation,
|
| + ChromeMetricsStatus metrics_status,
|
| + CleanerLogsStatus cleaner_logs_status,
|
| + ChromePromptImpl::OnPromptUser on_prompt_user,
|
| + base::OnceClosure on_connection_closed,
|
| + ChromeCleanerRunner::ProcessDoneCallback on_process_done,
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
| + auto cleaner_runner = make_scoped_refptr(new ChromeCleanerRunner(
|
| + cleaner_executable_path, reporter_invocation, metrics_status,
|
| + cleaner_logs_status, std::move(on_prompt_user),
|
| + std::move(on_connection_closed), std::move(on_process_done),
|
| + std::move(task_runner)));
|
| + auto launch_and_wait = base::BindOnce(
|
| + &ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread,
|
| + cleaner_runner);
|
| + auto process_done =
|
| + base::BindOnce(&ChromeCleanerRunner::OnProcessDone, cleaner_runner);
|
| + base::PostTaskWithTraitsAndReplyWithResult(
|
| + FROM_HERE,
|
| + // LaunchAndWaitForExitOnBackgroundThread creates (MayBlock()) and joins
|
| + // (WithBaseSyncPrimitives()) a process.
|
| + {base::MayBlock(), base::WithBaseSyncPrimitives(),
|
| + base::TaskPriority::BACKGROUND,
|
| + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
| + std::move(launch_and_wait), std::move(process_done));
|
| +}
|
| +
|
| +ChromeCleanerRunner::ChromeCleanerRunner(
|
| + const base::FilePath& cleaner_executable_path,
|
| + const SwReporterInvocation& reporter_invocation,
|
| + ChromeMetricsStatus metrics_status,
|
| + CleanerLogsStatus cleaner_logs_status,
|
| + ChromePromptImpl::OnPromptUser on_prompt_user,
|
| + base::OnceClosure on_connection_closed,
|
| + ProcessDoneCallback on_process_done,
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner)
|
| + : task_runner_(std::move(task_runner)),
|
| + cleaner_command_line_(cleaner_executable_path),
|
| + on_prompt_user_(std::move(on_prompt_user)),
|
| + on_connection_closed_(std::move(on_connection_closed)),
|
| + on_process_done_(std::move(on_process_done)) {
|
| + DCHECK(base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature));
|
| + DCHECK(on_prompt_user_);
|
| + DCHECK(on_connection_closed_);
|
| + DCHECK(on_process_done_);
|
| + DCHECK(!cleaner_executable_path.empty());
|
| +
|
| + // Add the non-IPC switches that should be passed to the Cleaner process.
|
| +
|
| + // Add switches that pass information about this Chrome installation.
|
| + cleaner_command_line_.AppendSwitchASCII(chrome_cleaner::kChromeVersionSwitch,
|
| + version_info::GetVersionNumber());
|
| + cleaner_command_line_.AppendSwitchASCII(chrome_cleaner::kChromeChannelSwitch,
|
| + base::IntToString(ChannelAsInt()));
|
| + base::FilePath chrome_exe_path;
|
| + PathService::Get(base::FILE_EXE, &chrome_exe_path);
|
| + cleaner_command_line_.AppendSwitchPath(chrome_cleaner::kChromeExePathSwitch,
|
| + chrome_exe_path);
|
| + if (!InstallUtil::IsPerUserInstall())
|
| + cleaner_command_line_.AppendSwitch(
|
| + chrome_cleaner::kChromeSystemInstallSwitch);
|
| +
|
| + // Start the cleaner process in scanning mode.
|
| + cleaner_command_line_.AppendSwitchASCII(
|
| + chrome_cleaner::kExecutionModeSwitch,
|
| + base::IntToString(
|
| + static_cast<int>(chrome_cleaner::ExecutionMode::kScanning)));
|
| +
|
| + // If set, forward the engine flag from the reporter. Otherwise, set the
|
| + // engine flag explicitly to 1.
|
| + const std::string& reporter_engine =
|
| + reporter_invocation.command_line.GetSwitchValueASCII(
|
| + chrome_cleaner::kEngineSwitch);
|
| + cleaner_command_line_.AppendSwitchASCII(
|
| + chrome_cleaner::kEngineSwitch,
|
| + reporter_engine.empty() ? "1" : reporter_engine);
|
| +
|
| + // If metrics is enabled, we can enable crash reporting in the Chrome Cleaner
|
| + // process.
|
| + if (metrics_status == ChromeMetricsStatus::kEnabled) {
|
| + cleaner_command_line_.AppendSwitch(chrome_cleaner::kUmaUserSwitch);
|
| + cleaner_command_line_.AppendSwitch(
|
| + chrome_cleaner::kEnableCrashReportingSwitch);
|
| + }
|
| +
|
| + // Enable logs upload for users who have opted into safe browsing extended
|
| + // reporting v2.
|
| + if (cleaner_logs_status == CleanerLogsStatus::kUploadEnabled)
|
| + cleaner_command_line_.AppendSwitch(
|
| + chrome_cleaner::kEnableCleanerLoggingSwitch);
|
| +}
|
| +
|
| +ChromeCleanerRunner::LaunchStatus
|
| +ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread() {
|
| + mojo::edk::OutgoingBrokerClientInvitation invitation;
|
| + std::string mojo_pipe_token = mojo::edk::GenerateRandomToken();
|
| + mojo::ScopedMessagePipeHandle mojo_pipe =
|
| + invitation.AttachMessagePipe(mojo_pipe_token);
|
| + cleaner_command_line_.AppendSwitchASCII(
|
| + chrome_cleaner::kChromeMojoPipeTokenSwitch, mojo_pipe_token);
|
| +
|
| + mojo::edk::PlatformChannelPair channel;
|
| + base::HandlesToInheritVector handles_to_inherit;
|
| + channel.PrepareToPassClientHandleToChildProcess(&cleaner_command_line_,
|
| + &handles_to_inherit);
|
| + base::LaunchOptions launch_options;
|
| + launch_options.handles_to_inherit = &handles_to_inherit;
|
| +
|
| + base::Process cleaner_process =
|
| + g_test_delegate
|
| + ? g_test_delegate->LaunchTestProcess(cleaner_command_line_,
|
| + launch_options)
|
| + : base::LaunchProcess(cleaner_command_line_, launch_options);
|
| +
|
| + constexpr int kBadProcessExitCode = std::numeric_limits<int>::max();
|
| + if (!cleaner_process.IsValid())
|
| + return {false, kBadProcessExitCode};
|
| +
|
| + // ChromePromptImpl tasks will need to run on the IO thread. There is no
|
| + // need to synchronize its creation, since the client end will wait for this
|
| + // initialization to be done before sending requests.
|
| + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
|
| + ->PostTask(FROM_HERE,
|
| + base::BindOnce(&ChromeCleanerRunner::CreateChromePromptImpl,
|
| + base::RetainedRef(this),
|
| + chrome_cleaner::mojom::ChromePromptRequest(
|
| + std::move(mojo_pipe))));
|
| +
|
| + invitation.Send(
|
| + cleaner_process.Handle(),
|
| + mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
|
| + channel.PassServerHandle()));
|
| +
|
| + int exit_code = kBadProcessExitCode;
|
| + if (cleaner_process.WaitForExit(&exit_code))
|
| + return {true, exit_code};
|
| + return {false, kBadProcessExitCode};
|
| +}
|
| +
|
| +ChromeCleanerRunner::~ChromeCleanerRunner() {
|
| + if (chrome_prompt_impl_) {
|
| + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
|
| + ->PostTask(FROM_HERE, base::Bind(&ReleaseChromePromptImpl,
|
| + base::Passed(&chrome_prompt_impl_)));
|
| + }
|
| +}
|
| +
|
| +void ChromeCleanerRunner::CreateChromePromptImpl(
|
| + ChromePromptRequest chrome_prompt_request) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK(!chrome_prompt_impl_);
|
| +
|
| + chrome_prompt_impl_ = base::MakeUnique<ChromePromptImpl>(
|
| + std::move(chrome_prompt_request),
|
| + base::Bind(&ChromeCleanerRunner::OnConnectionClosed,
|
| + base::RetainedRef(this)),
|
| + base::Bind(&ChromeCleanerRunner::OnPromptUser, base::RetainedRef(this)));
|
| +}
|
| +
|
| +void ChromeCleanerRunner::OnPromptUser(
|
| + std::unique_ptr<std::set<base::FilePath>> files_to_delete,
|
| + ChromePrompt::PromptUserCallback prompt_user_callback) {
|
| + if (on_prompt_user_) {
|
| + task_runner_->PostTask(FROM_HERE,
|
| + base::BindOnce(std::move(on_prompt_user_),
|
| + base::Passed(&files_to_delete),
|
| + base::Passed(&prompt_user_callback)));
|
| + }
|
| +}
|
| +
|
| +void ChromeCleanerRunner::OnConnectionClosed() {
|
| + if (on_connection_closed_)
|
| + task_runner_->PostTask(FROM_HERE, std::move(on_connection_closed_));
|
| +}
|
| +
|
| +void ChromeCleanerRunner::OnProcessDone(LaunchStatus launch_status) {
|
| + if (on_process_done_) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::BindOnce(std::move(on_process_done_), launch_status));
|
| + }
|
| +}
|
| +
|
| +void SetChromeCleanerRunnerTestDelegateForTesting(
|
| + ChromeCleanerRunnerTestDelegate* test_delegate) {
|
| + g_test_delegate = test_delegate;
|
| +}
|
| +
|
| +} // namespace safe_browsing
|
|
|