// Copyright 2018 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/chrome_cleaner/logging/cleaner_logging_service.h"

#include <memory>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/win/i18n.h"
#include "base/win/windows_version.h"
#include "chrome/chrome_cleaner/chrome_utils/chrome_util.h"
#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
#include "chrome/chrome_cleaner/constants/chrome_cleanup_tool_branding.h"
#include "chrome/chrome_cleaner/constants/version.h"
#include "chrome/chrome_cleaner/logging/api_keys.h"
#include "chrome/chrome_cleaner/logging/pending_logs_service.h"
#include "chrome/chrome_cleaner/logging/proto/removal_status.pb.h"
#include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h"
#include "chrome/chrome_cleaner/logging/registry_logger.h"
#include "chrome/chrome_cleaner/logging/utils.h"
#include "chrome/chrome_cleaner/os/disk_util.h"
#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
#include "chrome/chrome_cleaner/os/file_removal_status_updater.h"
#include "chrome/chrome_cleaner/os/rebooter.h"
#include "chrome/chrome_cleaner/os/registry_util.h"
#include "chrome/chrome_cleaner/os/resource_util.h"
#include "chrome/chrome_cleaner/os/system_util.h"
#include "chrome/chrome_cleaner/settings/settings.h"
#include "chrome/chrome_cleaner/strings/string_util.h"
#include "components/chrome_cleaner/public/constants/constants.h"

namespace chrome_cleaner {

namespace {
// TODO(joenotcharles): Refer to the report definition in the "data" section.
constexpr net::NetworkTrafficAnnotationTag kCleanerReportTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("chrome_cleanup_report", R"(
          semantics {
            sender: "Chrome Cleanup"
            description:
              "Chrome on Windows is able to detect and remove software that "
              "violates Google's Unwanted Software Policy "
              "(https://www.google.com/about/unwanted-software-policy.html). "
              "When potentially unwanted software is detected in the "
              "background, Chrome offers to remove it. If the user accepts the "
              "cleanup and chooses to \"Report details to Google\", Chrome "
              "will upload details of the unwanted software and its removal, "
              "as well as some details about the system, to help Google track "
              "the spread of unwanted software. "
              "The user can also use the settings page to ask Chrome to search "
              "for unwanted software and remove it. In this case if the user "
              "chooses \"Report details to Google\", the system details will "
              "be uploaded to Google whether or not unwanted software is found."
            trigger:
              "The user either accepted a prompt to remove unwanted software, "
              "or went to \"Clean up computer\" in the settings page and chose "
              "to \"Find harmful software\", and enabled \"Report details to "
              "Google\"."
            data:
              "The user's Chrome version, Windows version, and locale, file "
              "metadata related to the unwanted software that was detected, "
              "automatically installed Chrome extensions, and system settings "
              "commonly used by malicious software as described at "
              "https://www.google.com/chrome/privacy/whitepaper.html#unwantedsoftware. "
              "Contents of files are never reported. No user identifiers are "
              "reported, and common user identifiers found in metadata are "
              "replaced with generic strings, but it is possible some metadata "
              "may contain personally identifiable information. The complete "
              "data specification is at "
              "https://cs.chromium.org/chromium/src/chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.proto."
            destination: GOOGLE_OWNED_SERVICE
          }
          policy {
            cookies_allowed: NO
            setting:
              "Chrome Cleanup can be explicitly requested by the user in "
              "\"Clean up computer\" in the \"Reset and cleanup\" section of "
              "settings, under Advanced. To disable this report, turn off "
              "\"Report details to Google\" before choosing \"Find and remove "
              "harmful software\"."
            chrome_policy {
              ChromeCleanupReportingEnabled {
                ChromeCleanupReportingEnabled: false
              }
              ChromeCleanupEnabled {
                ChromeCleanupEnabled: false
              }
            }
          }
          comments:
            "If ChromeCleanupEnabled is set to \"false\", Chrome Cleanup will "
            "never run, so no reports will be uploaded to Google. Otherwise, "
            "ChromeCleanupReportingEnabled can be used to override the "
            "\"Report details to Google\" control: if it is set to \"true\", "
            "reports will always be sent, and if it is set to \"false\", "
            "reports will never be sent."
          )");

// Convert a FileInformation proto object to its corresponding
// internal::FileInformation struct. This function is thread lock safe.
void ProtoObjectToFileInformation(const FileInformation& proto_file_information,
                                  internal::FileInformation* file_information) {
  DCHECK(file_information);
  file_information->path = base::UTF8ToUTF16(proto_file_information.path());
  file_information->creation_date = proto_file_information.creation_date();
  file_information->last_modified_date =
      proto_file_information.last_modified_date();
  file_information->sha256 = proto_file_information.sha256();
  file_information->size = proto_file_information.size();
  file_information->company_name =
      base::UTF8ToUTF16(proto_file_information.company_name());
  file_information->company_short_name =
      base::UTF8ToUTF16(proto_file_information.company_short_name());
  file_information->product_name =
      base::UTF8ToUTF16(proto_file_information.product_name());
  file_information->product_short_name =
      base::UTF8ToUTF16(proto_file_information.product_short_name());
  file_information->internal_name =
      base::UTF8ToUTF16(proto_file_information.internal_name());
  file_information->original_filename =
      base::UTF8ToUTF16(proto_file_information.original_filename());
  file_information->file_description =
      base::UTF8ToUTF16(proto_file_information.file_description());
  file_information->file_version =
      base::UTF8ToUTF16(proto_file_information.file_version());
  file_information->active_file = proto_file_information.active_file();
}

}  // namespace

void AppendFileInformation(const FileInformation& file,
                           MessageBuilder* builder) {
  internal::FileInformation file_information;
  ProtoObjectToFileInformation(file, &file_information);
  builder->Add(FileInformationToString(file_information));
}

void AppendFolderInformation(const FolderInformation& folder,
                             MessageBuilder* builder) {
  if (folder.path().empty())
    return;

  builder->Add(L"path = '", folder.path(), L"'");
  if (!folder.creation_date().empty())
    builder->Add(L", folder_creation_date = '", folder.creation_date(), L"'");
  if (!folder.last_modified_date().empty()) {
    builder->Add(L", folder_last_modified_date = '",
                 folder.last_modified_date(), L"'");
  }
}

void AppendMatchedFile(const MatchedFile& file, MessageBuilder* builder) {
  AppendFileInformation(file.file_information(), builder);
  builder->Add(L", removal_status = ", file.removal_status());
  builder->Add(L", quarantine_status = ", file.quarantine_status());
}

void AppendMatchedRegistryEntry(const MatchedRegistryEntry& registry,
                                MessageBuilder* builder) {
  builder->Add(registry.key_path(), L"\\", registry.value_name(), L" ",
               registry.value_substring());
}

void AppendScheduledTask(const ScheduledTask& scheduled_task,
                         MessageBuilder* builder) {
  MessageBuilder::ScopedIndent scoped_indent(builder);
  builder->AddLine(scheduled_task.description(), L" (", scheduled_task.name(),
                   "):");

  MessageBuilder::ScopedIndent scoped_indent_2(builder);
  builder->AddHeaderLine(L"Actions");
  for (auto action : scheduled_task.actions()) {
    MessageBuilder::ScopedIndent scoped_indent(builder);
    builder->Add(L"File information: ");
    AppendFileInformation(action.file_information(), builder);
    builder->NewLine();
    builder->AddFieldValueLine(L"Working directory: ", action.working_dir());
    builder->AddFieldValueLine(L"Arguments: ", action.arguments());
  }
}

ChromeCleanerReport::CleanerStartup GetCleanerStartupFromCommandLine(
    const base::CommandLine* command_line) {
  if (!command_line->HasSwitch(kChromePromptSwitch))
    return ChromeCleanerReport::CLEANER_STARTUP_NOT_PROMPTED;

  std::string chrome_prompt_string =
      command_line->GetSwitchValueASCII(kChromePromptSwitch);
  int chrome_prompt_value = 0;
  if (base::StringToInt(chrome_prompt_string, &chrome_prompt_value) &&
      ChromeCleanerReport_CleanerStartup_IsValid(chrome_prompt_value) &&
      (chrome_prompt_value == ChromeCleanerReport::CLEANER_STARTUP_PROMPTED ||
       chrome_prompt_value ==
           ChromeCleanerReport::CLEANER_STARTUP_SHOWN_FROM_MENU ||
       chrome_prompt_value ==
           ChromeCleanerReport::CLEANER_STARTUP_USER_INITIATED)) {
    return static_cast<ChromeCleanerReport::CleanerStartup>(
        chrome_prompt_value);
  }

  LOG(ERROR) << "Invalid value passed to --" << kChromePromptSwitch << ": '"
             << chrome_prompt_string << "'.";
  return ChromeCleanerReport::CLEANER_STARTUP_UNKNOWN;
}

CleanerLoggingService* CleanerLoggingService::GetInstance() {
  return base::Singleton<CleanerLoggingService>::get();
}

// Please avoid setting any state here, all setup should be done in
// SetupInitialState to allow Terminate to reset this class to its default
// state.
CleanerLoggingService::CleanerLoggingService()
    : uploads_enabled_(false),
      initialized_(false),
      sampler_(DetailedInfoSampler::kDefaultMaxFiles) {}

CleanerLoggingService::~CleanerLoggingService() {
  // If initialize is called, the function |Terminate| must be called by the
  // user of this class before deleting this object.
  DCHECK(!initialized_)
      << "'Terminate' must be called before deleting CleanerLoggingService.";
}

void CleanerLoggingService::Initialize(RegistryLogger* registry_logger) {
  DCHECK(!initialized_) << "CleanerLoggingService already initialized.";
  EnableUploads(false, registry_logger);

  FileRemovalStatusUpdater::GetInstance()->Clear();

  logging::SetLogMessageHandler(
      CleanerLoggingService::LogMessageHandlerFunction);

  Settings* settings = Settings::GetInstance();
  const bool metrics_enabled = settings->metrics_enabled();
  const bool sber_enabled = settings->sber_enabled();
  const std::string cleanup_id = settings->cleanup_id();
  const Engine::Name engine = settings->engine();
  const std::string engine_version = settings->engine_version();

  const base::CommandLine* command_line =
      base::CommandLine::ForCurrentProcess();
  const ChromeCleanerReport::CleanerStartup cleaner_startup =
      GetCleanerStartupFromCommandLine(command_line);
  const bool chrome_prompt =
      cleaner_startup == ChromeCleanerReport::CLEANER_STARTUP_PROMPTED;

  int channel = 0;
  bool has_chrome_channel = GetChromeChannelFromCommandLine(&channel);

  const bool post_reboot = Rebooter::IsPostReboot();

  std::vector<base::string16> languages;
  base::win::i18n::GetUserPreferredUILanguageList(&languages);

  base::string16 chrome_version_string;
  bool chrome_version_string_succeeded =
      RetrieveChromeVersionAndInstalledDomain(&chrome_version_string, nullptr);

  base::CPU cpu_info;
  std::string cpu_architecture = base::SysInfo::OperatingSystemArchitecture();

  {
    base::AutoLock lock(raw_log_lines_buffer_lock_);
    raw_log_lines_buffer_.clear();
  }

  {
    base::AutoLock lock(lock_);

    // Ensure that logging report starts in a cleared state.
    chrome_cleaner_report_.Clear();
    matched_files_.clear();
    matched_folders_.clear();

    // Initialize with invalid exit code to identify whether it was set or not.
    chrome_cleaner_report_.set_exit_code(RESULT_CODE_PENDING);
    chrome_cleaner_report_.set_intermediate_log(true);
    chrome_cleaner_report_.set_uma_user(metrics_enabled);
    chrome_cleaner_report_.set_sber_enabled(sber_enabled);
    chrome_cleaner_report_.set_post_reboot(post_reboot);
    // TODO(veranika): this field is deprecated. Stop reporting it.
    chrome_cleaner_report_.set_chrome_prompt(chrome_prompt);
    if (cleaner_startup != ChromeCleanerReport::CLEANER_STARTUP_UNSPECIFIED)
      chrome_cleaner_report_.set_cleaner_startup(cleaner_startup);
    chrome_cleaner_report_.set_cleanup_id(cleanup_id);

    // Set invariant environment / machine data.
    ChromeCleanerReport_EnvironmentData* env_data =
        chrome_cleaner_report_.mutable_environment();
    env_data->set_windows_version(static_cast<int>(base::win::GetVersion()));
    env_data->set_cleaner_version(CHROME_CLEANER_VERSION_UTF8_STRING);
    if (languages.size() > 0)
      env_data->set_default_locale(base::WideToUTF8(languages[0]));
    env_data->set_detailed_system_report(false);
    env_data->set_bitness(IsX64Process() ? 64 : 32);

    if (chrome_version_string_succeeded)
      env_data->set_chrome_version(base::WideToUTF8(chrome_version_string));

    if (has_chrome_channel)
      env_data->set_chrome_channel(channel);

    ChromeCleanerReport_EnvironmentData_Machine* machine =
        env_data->mutable_machine();
    machine->set_cpu_architecture(cpu_architecture);
    machine->set_cpu_vendor(cpu_info.vendor_name());
    machine->set_cpuid(cpu_info.signature());

    env_data->mutable_engine()->set_name(engine);
    if (!engine_version.empty())
      env_data->mutable_engine()->set_version(engine_version);

    initialized_ = true;
  }
}

void CleanerLoggingService::Terminate() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(initialized_) << "Logging service is not initialized.";

  size_t num_log_lines = 0;
  {
    // Get all values from the logging report we are interested in before
    // clearing it.
    base::AutoLock lock(raw_log_lines_buffer_lock_);
    num_log_lines = raw_log_lines_buffer_.size();
  }

  if (num_log_lines > 0) {
    LOG(WARNING) << "At least the last " << num_log_lines
                 << " log lines have not been uploaded to Safe Browsing.";
  }

  {
    base::AutoLock lock(raw_log_lines_buffer_lock_);
    raw_log_lines_buffer_.clear();
    initialized_ = false;
  }
}

void CleanerLoggingService::SendLogsToSafeBrowsing(
    const UploadResultCallback& done_callback,
    RegistryLogger* registry_logger) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(initialized_);

  // If reporting is not enabled or required, call |done_callback|
  if (!uploads_enabled() || !IsReportingNeeded())
    return done_callback.Run(false);  // false since no logs were uploaded.

  ChromeCleanerReport chrome_cleaner_report;
  GetCurrentChromeCleanerReport(&chrome_cleaner_report);

  {
    base::AutoLock lock(lock_);
    // No need to repeat the log lines in subsequent uploads.
    chrome_cleaner_report_.clear_raw_log_line();
    chrome_cleaner_report_.mutable_environment()->set_detailed_system_report(
        false);
  }

  // TODO(csharp): Move this to the main controller.
  // Register a task to try again if we ever fail half way through uploading
  // |chrome_cleaner_report|. Will be cleared upon success in
  // |OnReportUploadResult|.
  ClearTempLogFile(registry_logger);
  PendingLogsService::ScheduleLogsUploadTask(PRODUCT_SHORTNAME_STRING,
                                             chrome_cleaner_report,
                                             &temp_log_file_, registry_logger);

  std::string serialized_report;
  if (!chrome_cleaner_report.SerializeToString(&serialized_report)) {
    LOG(WARNING) << "Failed to serialize report";
    return done_callback.Run(false);  // false since no logs were uploaded.
  }

  SafeBrowsingReporter::UploadReport(
      base::BindRepeating(&CleanerLoggingService::OnReportUploadResult,
                          base::Unretained(this), done_callback,
                          registry_logger),
      kSafeBrowsingCleanerUrl, serialized_report,
      kCleanerReportTrafficAnnotation);
}

void CleanerLoggingService::CancelWaitForShutdown() {
  SafeBrowsingReporter::CancelWaitForShutdown();
}

void CleanerLoggingService::EnableUploads(bool enable,
                                          RegistryLogger* registry_logger) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (enable == uploads_enabled_)
    return;
  uploads_enabled_ = enable;

  // Make sure not to keep any scheduled logs upload if the user opts-out of
  // logs upload. TODO(csharp): maybe we should also clear all other pending
  // logs, not just ours.
  if (!enable)
    ClearTempLogFile(registry_logger);
}

bool CleanerLoggingService::uploads_enabled() const {
  return uploads_enabled_;
}

void CleanerLoggingService::SetDetailedSystemReport(
    bool detailed_system_report) {
  base::AutoLock lock(lock_);
  chrome_cleaner_report_.mutable_environment()->set_detailed_system_report(
      detailed_system_report);
}

bool CleanerLoggingService::detailed_system_report_enabled() const {
  return chrome_cleaner_report_.environment().detailed_system_report();
}

void CleanerLoggingService::AddFoundUwS(const std::string& found_uws_name) {
  base::AutoLock lock(lock_);
  chrome_cleaner_report_.add_found_uws(found_uws_name);
}

void CleanerLoggingService::AddDetectedUwS(const PUPData::PUP* found_uws,
                                           UwSDetectedFlags flags) {
  DCHECK(found_uws);
  UwS detected_uws =
      PUPToUwS(found_uws, flags, /*cleaning_files=*/true, &sampler_);
  AddDetectedUwS(detected_uws);
}

void CleanerLoggingService::AddDetectedUwS(const UwS& uws) {
  base::AutoLock lock(lock_);
  UwS* added_uws = chrome_cleaner_report_.add_detected_uws();
  *added_uws = uws;
  UpdateMatchedFilesAndFoldersMaps(added_uws);
}

void CleanerLoggingService::SetExitCode(ResultCode exit_code) {
  ResultCode previous_exit_code = RESULT_CODE_INVALID;
  {
    base::AutoLock lock(lock_);
    previous_exit_code =
        static_cast<ResultCode>(chrome_cleaner_report_.exit_code());
    chrome_cleaner_report_.set_exit_code(exit_code);
    // Once an exit code has been provided, this is not an intermediate log
    // anymore.
    chrome_cleaner_report_.set_intermediate_log(false);
  }
  // The DCHECK can't be under |lock_|. The only valid reason to overwrite a non
  // pending exit code, is when we failed to read pending upload log files.
  DCHECK(previous_exit_code == RESULT_CODE_PENDING ||
         exit_code == RESULT_CODE_FAILED_TO_READ_UPLOAD_LOGS_FILE);
}

void CleanerLoggingService::AddLoadedModule(
    const base::string16& name,
    ModuleHost module_host,
    const internal::FileInformation& file_information) {
  FileInformation reported_file_information;
  FileInformationToProtoObject(file_information, &reported_file_information);

  base::AutoLock lock(lock_);
  ChromeCleanerReport::SystemReport::LoadedModule* loaded_module =
      chrome_cleaner_report_.mutable_system_report()->add_loaded_modules();
  loaded_module->set_name(base::UTF16ToUTF8(name));
  loaded_module->set_host(module_host);
  *loaded_module->mutable_file_information() = reported_file_information;
}

void CleanerLoggingService::AddService(
    const base::string16& display_name,
    const base::string16& service_name,
    const internal::FileInformation& file_information) {
  FileInformation reported_file_information;
  FileInformationToProtoObject(file_information, &reported_file_information);

  base::AutoLock lock(lock_);
  ChromeCleanerReport::SystemReport::Service* service =
      chrome_cleaner_report_.mutable_system_report()->add_services();
  service->set_display_name(base::UTF16ToUTF8(display_name));
  service->set_service_name(base::UTF16ToUTF8(service_name));
  *service->mutable_file_information() = reported_file_information;
}

void CleanerLoggingService::AddInstalledProgram(
    const base::FilePath& folder_path) {
  FolderInformation folder_information;
  if (!RetrieveFolderInformation(folder_path, &folder_information))
    return;

  base::AutoLock lock(lock_);
  ChromeCleanerReport::SystemReport::InstalledProgram* installed_program =
      chrome_cleaner_report_.mutable_system_report()->add_installed_programs();
  *installed_program->mutable_folder_information() = folder_information;
}

void CleanerLoggingService::AddProcess(
    const base::string16& name,
    const internal::FileInformation& file_information) {
  FileInformation reported_file_information;
  FileInformationToProtoObject(file_information, &reported_file_information);

  base::AutoLock lock(lock_);
  ChromeCleanerReport::SystemReport::Process* process =
      chrome_cleaner_report_.mutable_system_report()->add_processes();
  process->set_name(base::UTF16ToUTF8(name));
  *process->mutable_file_information() = reported_file_information;
}

void CleanerLoggingService::AddRegistryValue(
    const internal::RegistryValue& registry_value,
    const std::vector<internal::FileInformation>& file_informations) {
  RegistryValue new_registry_value;
  new_registry_value.set_key_path(base::UTF16ToUTF8(registry_value.key_path));
  new_registry_value.set_value_name(
      base::UTF16ToUTF8(registry_value.value_name));
  new_registry_value.set_data(base::UTF16ToUTF8(registry_value.data));

  for (const auto& file_information : file_informations) {
    FileInformation* reported_file_information =
        new_registry_value.add_file_informations();
    FileInformationToProtoObject(file_information, reported_file_information);
  }

  base::AutoLock lock(lock_);
  *chrome_cleaner_report_.mutable_system_report()->add_registry_values() =
      new_registry_value;
}

void CleanerLoggingService::AddLayeredServiceProvider(
    const std::vector<base::string16>& guids,
    const internal::FileInformation& file_information) {
  ChromeCleanerReport_SystemReport_LayeredServiceProvider
      layered_service_provider;
  FileInformation* reported_file_information =
      layered_service_provider.mutable_file_information();
  FileInformationToProtoObject(file_information, reported_file_information);

  for (const auto& guid : guids)
    layered_service_provider.add_guids(base::UTF16ToUTF8(guid));

  base::AutoLock lock(lock_);
  *chrome_cleaner_report_.mutable_system_report()
       ->add_layered_service_providers() = layered_service_provider;
}

void CleanerLoggingService::SetWinInetProxySettings(
    const base::string16& config,
    const base::string16& bypass,
    const base::string16& auto_config_url,
    bool autodetect) {
  base::AutoLock lock(lock_);
  ChromeCleanerReport_SystemReport_SystemProxySettings*
      win_inet_proxy_settings = chrome_cleaner_report_.mutable_system_report()
                                    ->mutable_win_inet_proxy_settings();
  win_inet_proxy_settings->set_config(base::UTF16ToUTF8(config));
  win_inet_proxy_settings->set_bypass(base::UTF16ToUTF8(bypass));
  win_inet_proxy_settings->set_auto_config_url(
      base::UTF16ToUTF8(auto_config_url));
  win_inet_proxy_settings->set_autodetect(autodetect);
}

void CleanerLoggingService::SetWinHttpProxySettings(
    const base::string16& config,
    const base::string16& bypass) {
  base::AutoLock lock(lock_);
  ChromeCleanerReport_SystemReport_SystemProxySettings*
      win_http_proxy_settings = chrome_cleaner_report_.mutable_system_report()
                                    ->mutable_win_http_proxy_settings();
  win_http_proxy_settings->set_config(base::UTF16ToUTF8(config));
  win_http_proxy_settings->set_bypass(base::UTF16ToUTF8(bypass));
}

void CleanerLoggingService::AddInstalledExtension(
    const base::string16& extension_id,
    ExtensionInstallMethod install_method,
    const std::vector<internal::FileInformation>& extension_files) {
  base::AutoLock lock(lock_);
  ChromeCleanerReport_SystemReport_InstalledExtension* installed_extension =
      chrome_cleaner_report_.mutable_system_report()
          ->add_installed_extensions();
  installed_extension->set_extension_id(base::UTF16ToUTF8(extension_id));
  installed_extension->set_install_method(install_method);
  for (const auto& file : extension_files) {
    FileInformation proto_file_information;
    FileInformationToProtoObject(file, &proto_file_information);
    *installed_extension->add_extension_files() = proto_file_information;
  }
}

void CleanerLoggingService::AddScheduledTask(
    const base::string16& name,
    const base::string16& description,
    const std::vector<internal::FileInformation>& actions) {
  ScheduledTask scheduled_task;
  scheduled_task.set_name(base::UTF16ToUTF8(name));
  scheduled_task.set_description(base::UTF16ToUTF8(description));

  for (const auto& action : actions) {
    FileInformation* reported_action =
        scheduled_task.add_actions()->mutable_file_information();
    FileInformationToProtoObject(action, reported_action);
  }

  base::AutoLock lock(lock_);
  *chrome_cleaner_report_.mutable_system_report()->add_scheduled_tasks() =
      scheduled_task;
}

void CleanerLoggingService::AddShortcutData(
    const base::string16& lnk_path,
    const base::string16& executable_path,
    const std::string& executable_hash,
    const std::vector<base::string16>& command_line_arguments) {
  base::AutoLock lock(lock_);
  ChromeCleanerReport_SystemReport_ShortcutData* shortcut_data =
      chrome_cleaner_report_.mutable_system_report()->add_shortcut_data();
  shortcut_data->set_lnk_path(base::UTF16ToUTF8(lnk_path));
  shortcut_data->set_executable_path(base::UTF16ToUTF8(executable_path));
  shortcut_data->set_executable_hash(executable_hash);
  for (const auto& argument : command_line_arguments) {
    shortcut_data->add_command_line_arguments(base::UTF16ToUTF8(argument));
  }
}

void CleanerLoggingService::SetFoundModifiedChromeShortcuts(
    bool /*found_modified_shortcuts*/) {}

void CleanerLoggingService::SetScannedLocations(
    const std::vector<UwS::TraceLocation>& /*scanned_locations*/) {}

void CleanerLoggingService::LogProcessInformation(
    SandboxType process_type,
    const SystemResourceUsage& usage) {
  ProcessInformation info =
      GetProcessInformationProtoObject(process_type, usage);
  base::AutoLock lock(lock_);
  chrome_cleaner_report_.add_process_information()->Swap(&info);
}

bool CleanerLoggingService::AllExpectedRemovalsConfirmed() const {
  FileRemovalStatusUpdater* status_updater =
      FileRemovalStatusUpdater::GetInstance();

  base::AutoLock lock(lock_);
  for (const UwS& uws : chrome_cleaner_report_.detected_uws()) {
    if (uws.state() != UwS::REMOVABLE)
      continue;
    for (const MatchedFile& file : uws.files()) {
      base::string16 sanitized_path =
          base::UTF8ToUTF16(file.file_information().path());
      RemovalStatus removal_status =
          status_updater->GetRemovalStatusOfSanitizedPath(sanitized_path);

      // If the removal status was never set in FileRemovalStatusUpdater, fall
      // back to the status that was originally set when the MatchedFile object
      // was created.
      if (removal_status == REMOVAL_STATUS_UNSPECIFIED)
        removal_status = file.removal_status();

      // Non-active files are collected in the report for later auditing, but
      // not expected to be removed.
      if (removal_status == REMOVAL_STATUS_MATCHED_ONLY &&
          !file.file_information().active_file()) {
        continue;
      }

      if (removal_status != REMOVAL_STATUS_REMOVED &&
          removal_status != REMOVAL_STATUS_SCHEDULED_FOR_REMOVAL &&
          removal_status != REMOVAL_STATUS_NOT_FOUND &&
          removal_status != REMOVAL_STATUS_SCHEDULED_FOR_REMOVAL_FALLBACK) {
        return false;
      }
    }
  }
  return true;
}

std::string CleanerLoggingService::RawReportContent() {
  ChromeCleanerReport chrome_cleaner_report;
  GetCurrentChromeCleanerReport(&chrome_cleaner_report);

  std::string chrome_cleaner_report_string;
  chrome_cleaner_report.SerializeToString(&chrome_cleaner_report_string);
  return chrome_cleaner_report_string;
}

bool CleanerLoggingService::ReadContentFromFile(
    const base::FilePath& log_file) {
  std::string proto_string;
  if (!base::ReadFileToString(log_file, &proto_string)) {
    LOG(ERROR) << "Can't read content of '" << SanitizePath(log_file) << "'.";
    return false;
  } else if (proto_string.empty()) {
    LOG(ERROR) << "Empty log file: " << SanitizePath(log_file);
    return false;
  }
  bool succeeded = false;
  {
    base::AutoLock lock(lock_);
    succeeded = chrome_cleaner_report_.ParseFromString(proto_string);
    if (succeeded) {
      matched_files_.clear();
      matched_folders_.clear();
      for (UwS& detected_uws : *chrome_cleaner_report_.mutable_detected_uws())
        UpdateMatchedFilesAndFoldersMaps(&detected_uws);
    }
  }
  if (!succeeded) {
    LOG(ERROR) << "Read invalid protobuf from '" << SanitizePath(log_file)
               << "'.";
    return false;
  }
  return true;
}

void CleanerLoggingService::ScheduleFallbackLogsUpload(
    RegistryLogger* registry_logger,
    ResultCode result_code) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(initialized_);
  // Even if we don't upload logs, we can still let Chrome UMA know we got to
  // this stage.
  DCHECK(registry_logger);
  registry_logger->WriteExitCode(result_code);

  if (!uploads_enabled())
    return;

  ChromeCleanerReport chrome_cleaner_report;
  GetCurrentChromeCleanerReport(&chrome_cleaner_report);
  chrome_cleaner_report.set_exit_code(result_code);

  ClearTempLogFile(registry_logger);
  PendingLogsService::ScheduleLogsUploadTask(PRODUCT_SHORTNAME_STRING,
                                             chrome_cleaner_report,
                                             &temp_log_file_, registry_logger);
}

void CleanerLoggingService::OnReportUploadResult(
    const UploadResultCallback& done_callback,
    RegistryLogger* registry_logger,
    SafeBrowsingReporter::Result result,
    const std::string& serialized_report,
    std::unique_ptr<ChromeFoilResponse> response) {
  DCHECK(registry_logger);
  if (result == SafeBrowsingReporter::Result::UPLOAD_SUCCESS)
    ClearTempLogFile(registry_logger);
  done_callback.Run(result == SafeBrowsingReporter::Result::UPLOAD_SUCCESS);
}

bool CleanerLoggingService::IsReportingNeeded() const {
  Settings* settings = Settings::GetInstance();
  if (settings->execution_mode() != ExecutionMode::kScanning &&
      settings->execution_mode() != ExecutionMode::kCleanup) {
    NOTREACHED();
    return false;
  }

  // Raw log lines are collected in vector raw_log_lines_buffer_ and moved to
  // proto field raw_log_line whenever the proto is generated. Logs should be
  // uploaded if either is non-empty.

  {
    base::AutoLock lock(raw_log_lines_buffer_lock_);
    if (!raw_log_lines_buffer_.empty())
      return true;
  }

  {
    base::AutoLock lock(lock_);
    return chrome_cleaner_report_.exit_code() != RESULT_CODE_PENDING ||
           chrome_cleaner_report_.raw_log_line_size() > 0 ||
           chrome_cleaner_report_.found_uws_size() > 0;
  }
}

void CleanerLoggingService::ClearTempLogFile(RegistryLogger* registry_logger) {
  if (!temp_log_file_.empty()) {
    PendingLogsService::ClearPendingLogFile(PRODUCT_SHORTNAME_STRING,
                                            temp_log_file_, registry_logger);
    temp_log_file_.clear();
  }
}

// static.
bool CleanerLoggingService::LogMessageHandlerFunction(int severity,
                                                      const char* file,
                                                      int line,
                                                      size_t message_start,
                                                      const std::string& str) {
  CleanerLoggingService* logging_service = CleanerLoggingService::GetInstance();
  std::string utf8_str;
  if (base::IsStringUTF8(str))
    utf8_str = str;
  else
    utf8_str = RemoveInvalidUTF8Chars(str);

  base::AutoLock lock(logging_service->raw_log_lines_buffer_lock_);
  logging_service->raw_log_lines_buffer_.push_back(utf8_str);

  // Returning false, pretending the event wasn't handled here, let the other
  // handlers receive it.
  return false;
}

void CleanerLoggingService::GetCurrentChromeCleanerReport(
    ChromeCleanerReport* chrome_cleaner_report) {
  DCHECK(chrome_cleaner_report);

  UpdateFileRemovalStatuses();

  std::vector<std::string> raw_log_lines_to_send;
  {
    base::AutoLock lock(raw_log_lines_buffer_lock_);
    raw_log_lines_to_send.reserve(raw_log_lines_buffer_.size());
    raw_log_lines_to_send.insert(raw_log_lines_to_send.begin(),
                                 raw_log_lines_buffer_.begin(),
                                 raw_log_lines_buffer_.end());
    raw_log_lines_buffer_.clear();
  }

  {
    base::AutoLock lock(lock_);
    for (const std::string& line : raw_log_lines_to_send)
      chrome_cleaner_report_.add_raw_log_line(line);
    chrome_cleaner_report->CopyFrom(chrome_cleaner_report_);
  }
}

void CleanerLoggingService::UpdateMatchedFilesAndFoldersMaps(UwS* added_uws) {
  for (MatchedFile& file : *added_uws->mutable_files())
    matched_files_[file.file_information().path()].push_back(&file);
  for (MatchedFolder& folder : *added_uws->mutable_folders())
    matched_folders_[folder.folder_information().path()].push_back(&folder);
}

void CleanerLoggingService::UpdateFileRemovalStatuses() {
  for (const auto& path_and_status :
       FileRemovalStatusUpdater::GetInstance()->GetAllRemovalStatuses()) {
    std::string sanitized_path = base::UTF16ToUTF8(path_and_status.first);
    FileRemovalStatusUpdater::FileRemovalStatus status = path_and_status.second;
    DCHECK(status.removal_status != REMOVAL_STATUS_UNSPECIFIED);

    bool known_matched_file = true;
    {
      base::AutoLock lock(lock_);

      auto file_it = matched_files_.find(sanitized_path);
      auto folder_it = matched_folders_.find(sanitized_path);

      if (file_it != matched_files_.end()) {
        for (MatchedFile* matched_file : file_it->second) {
          matched_file->set_removal_status(status.removal_status);
          matched_file->set_quarantine_status(status.quarantine_status);
        }
      } else if (folder_it != matched_folders_.end()) {
        for (MatchedFolder* matched_folder : folder_it->second) {
          matched_folder->set_removal_status(status.removal_status);
          // We don't quarantine folders. So the quarantine status should be
          // |QUARANTINE_STATUS_UNSPECIFIED| and we don't need to record it.
          DCHECK(status.quarantine_status == QUARANTINE_STATUS_UNSPECIFIED);
        }
      } else {
        known_matched_file = false;
      }
    }

    // Files that were deleted should be matched with an UwS by calling
    // AddDetectedUwS before logging. But there are some circumstances where
    // AddDetectedUwS is not called, such as when there are no existing files
    // for that UwS at the moment it is logged, so it should not be marked
    // removable. These should match up to circumstances where no files are
    // deleted, but just in case, log any file deletions that aren't matched to
    // an UwS for investigation.
    if (!known_matched_file) {
      FileInformation file_information;
      bool got_file_information = GetFileInformationProtoObject(
          status.path, /*detailed_information=*/true, &file_information);

      base::AutoLock lock(lock_);
      // Since the item might have been deleted at this point, just assume it
      // was a file.
      MatchedFile* file = nullptr;
      auto* unknown_uws = chrome_cleaner_report_.mutable_unknown_uws();
      for (int i = 0; i < unknown_uws->files_size(); i++) {
        if (unknown_uws->files(i).file_information().path() == sanitized_path) {
          file = unknown_uws->mutable_files(i);
          break;
        }
      }

      if (file == nullptr)
        file = chrome_cleaner_report_.mutable_unknown_uws()->add_files();

      if (got_file_information) {
        *file->mutable_file_information() = file_information;
      } else {
        // If we can't get the detailed file information, still record at least
        // the path.
        file->mutable_file_information()->set_path(sanitized_path);
      }
      file->set_removal_status(status.removal_status);
      file->set_quarantine_status(status.quarantine_status);
    }
  }
}

}  // namespace chrome_cleaner
