blob: d35eb83b4132169adb2d910e62b5e2f2fa6678a0 [file] [log] [blame]
// Copyright 2015 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 <limits.h>
#include <stdint.h>
#include <memory>
#include <queue>
#include <string>
#include "base/callback.h"
#include "base/command_line.h"
#include "base/time/time.h"
#include "base/version.h"
#include "chrome/browser/profiles/profile.h"
#include "components/chrome_cleaner/public/constants/constants.h"
namespace base {
class TaskRunner;
namespace safe_browsing {
class ChromeCleanerController;
// A special exit code identifying a failure to run the reporter.
const int kReporterNotLaunchedExitCode = INT_MAX;
// The number of days to wait before triggering another reporter run.
const int kDaysBetweenSuccessfulSwReporterRuns = 7;
// The number of days to wait before sending out reporter logs.
const int kDaysBetweenReporterLogsSent = 7;
// Identifies if an invocation was created during periodic reporter runs
// or because the user explicitly initiated a cleanup. The invocation type
// controls whether a prompt dialog will be shown to the user and under what
// conditions logs may be uploaded to Google.
// These values are used to send UMA information and are replicated in the
// enums.xml file, so the order MUST NOT CHANGE.
enum class SwReporterInvocationType {
// Default value that should never be used for valid invocations.
// Periodic runs of the reporter are initiated by Chrome after startup.
// If removable unwanted software is found the user may be prompted to
// run the Chrome Cleanup tool. Logs from the software reporter will only
// be uploaded if the user has opted-into SBER2 and if unwanted software
// is found on the system. The cleaner process in scanning mode will not
// upload logs.
// User-initiated runs in which the user has opted-out of sending details
// to Google. Those runs are intended to be completely driven from the
// Settings page, so a prompt dialog will not be shown to the user if
// removable unwanted software is found. Logs will not be uploaded from the
// reporter, even if the user has opted into SBER2, and cleaner logs will not
// be uploaded.
// User-initiated runs in which the user has not opted-out of sending
// details to Google. Those runs are intended to be completely driven from
// the Settings page, so a prompt dialog will not be shown to the user if
// removable unwanted software is found. Logs will be uploaded from both
// the reporter and the cleaner in scanning mode (which will only run if
// unwanted software is found by the reporter).
bool IsUserInitiated(SwReporterInvocationType invocation_type);
// Parameters used to invoke the sw_reporter component.
class SwReporterInvocation {
// Flags to control behaviours the Software Reporter should support by
// default. These flags are set in the Reporter installer, and experimental
// versions of the reporter will turn on the behaviours that are not yet
// supported.
using Behaviours = uint32_t;
enum : Behaviours {
explicit SwReporterInvocation(const base::CommandLine& command_line);
SwReporterInvocation(const SwReporterInvocation& invocation);
void operator=(const SwReporterInvocation& invocation);
// Fluent interface methods, intended to be used during initialization.
// Sample usage:
// auto invocation = SwReporterInvocation(command_line)
// .WithSuffix("MySuffix")
// .WithSupportedBehaviours(
// SwReporterInvocation::Behaviours::BEHAVIOUR_TRIGGER_PROMPT);
SwReporterInvocation& WithSuffix(const std::string& suffix);
SwReporterInvocation& WithSupportedBehaviours(
Behaviours supported_behaviours);
bool operator==(const SwReporterInvocation& other) const;
const base::CommandLine& command_line() const;
base::CommandLine& mutable_command_line();
Behaviours supported_behaviours() const;
bool BehaviourIsSupported(Behaviours intended_behaviour) const;
// Experimental versions of the reporter will write metrics to registry keys
// ending in |suffix_|. Those metrics should be copied to UMA histograms also
// ending in |suffix_|. For the canonical version, |suffix_| will be empty.
std::string suffix() const;
// Indicates if the invocation type allows logs to be uploaded by the
// reporter process.
bool reporter_logs_upload_enabled() const;
void set_reporter_logs_upload_enabled(bool reporter_logs_upload_enabled);
// Indicates if the invocation type allows logs to be uploaded by the
// cleaner process in scanning mode.
bool cleaner_logs_upload_enabled() const;
void set_cleaner_logs_upload_enabled(bool cleaner_logs_upload_enabled);
chrome_cleaner::ChromePromptValue chrome_prompt() const;
void set_chrome_prompt(chrome_cleaner::ChromePromptValue chrome_prompt);
base::CommandLine command_line_;
Behaviours supported_behaviours_ = BEHAVIOURS_ENABLED_BY_DEFAULT;
std::string suffix_;
bool reporter_logs_upload_enabled_ = false;
bool cleaner_logs_upload_enabled_ = false;
chrome_cleaner::ChromePromptValue chrome_prompt_ =
// These values are used to send UMA information and are replicated in the
// enums.xml file, so the order MUST NOT CHANGE.
enum class SwReporterInvocationResult {
// Tried to start a new run, but a user-initiated run was already
// happening. The UI should never allow this to happen.
// The reporter process timed-out while running.
// The on-demand reporter run failed to download a new version of the reporter
// component.
// The reporter failed to start.
// The reporter ended with a failure.
// The reporter ran successfully, but didn't find cleanable unwanted software.
// A periodic reporter sequence ran successfully and found cleanable unwanted
// software, but the user shouldn't be prompted at this time.
// The reporter ran successfully and found cleanable unwanted software, and
// a cleanup should be offered. A notification with this result should be
// immediately followed by an attempt to run the cleaner in scanning mode.
// Called when all reporter invocations have completed, with a result parameter
// indicating if they succeeded.
using OnReporterSequenceDone =
base::OnceCallback<void(SwReporterInvocationResult result)>;
class SwReporterInvocationSequence {
using Queue = std::queue<SwReporterInvocation>;
explicit SwReporterInvocationSequence(
const base::Version& version = base::Version());
SwReporterInvocationSequence(SwReporterInvocationSequence&& queue);
const SwReporterInvocationSequence& invocations_sequence);
virtual ~SwReporterInvocationSequence();
void PushInvocation(const SwReporterInvocation& invocation);
void operator=(SwReporterInvocationSequence&& queue);
void NotifySequenceDone(SwReporterInvocationResult result);
base::Version version() const;
const Queue& container() const;
Queue& mutable_container();
base::Version version_;
Queue container_;
// Invoked the first time this sequence run finishes or when the object
// gets destroyed if it's never invoked.
OnReporterSequenceDone on_sequence_done_;
// Tries to run the given invocations. If this runs successfully, than any
// calls made in the next |kDaysBetweenSuccessfulSwReporterRuns| days will be
// ignored.
// Each "run" of the sw_reporter component may aggregate the results of several
// executions of the tool with different command lines. |invocations| is the
// queue of SwReporters to execute as a single "run". When a new try is
// scheduled the entire queue is executed.
void MaybeStartSwReporter(SwReporterInvocationType invocation_type,
SwReporterInvocationSequence&& invocations);
// Returns true if the sw_reporter is allowed to run due to enterprise policies.
bool SwReporterIsAllowedByPolicy();
// Returns true if the sw_reported is allowed to report back results due to
// enterprise policies.
bool SwReporterReportingIsAllowedByPolicy(Profile* profile);
// A delegate used by tests to implement test doubles (e.g., stubs, fakes, or
// mocks).
// TODO( Replace this with a proper delegate that defines the
// default behaviour to be overriden (instead of defined) by tests.
class SwReporterTestingDelegate {
virtual ~SwReporterTestingDelegate() {}
// Invoked by tests in place of base::LaunchProcess.
virtual int LaunchReporter(const SwReporterInvocation& invocation) = 0;
// Invoked by tests to override the current time.
// See Now() in
virtual base::Time Now() const = 0;
// A task runner used to spawn the reporter process (which blocks).
// See ReporterRunner::ScheduleNextInvocation().
virtual base::TaskRunner* BlockingTaskRunner() const = 0;
// Invoked by tests to return a mock to the cleaner controller.
virtual ChromeCleanerController* GetCleanerController() = 0;
// Invoked by tests in place of the actual creation of the dialog controller.
virtual void CreateChromeCleanerDialogController() = 0;
// Set a delegate for testing. The implementation will not take ownership of
// |delegate| - it must remain valid until this function is called again to
// reset the delegate. If |delegate| is nullptr, any previous delegate is
// cleared.
void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate);
} // namespace safe_browsing