// Copyright (c) 2012 The Chromium OS 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 "debugd/src/debugd_dbus_adaptor.h"

#include <memory>
#include <utility>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/variant_dictionary.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/object_path.h>

#include "debugd/src/constants.h"
#include "debugd/src/error_utils.h"
#include "debugd/src/process_with_output.h"

namespace debugd {

namespace {

const char kDevCoredumpDBusErrorString[] =
    "org.chromium.debugd.error.DevCoreDump";

const char kShouldSendRlzPingKey[] = "should_send_rlz_ping";

const char kRlzEmbargoEndDateKey[] = "rlz_embargo_end_date";

}  // namespace

DebugdDBusAdaptor::DebugdDBusAdaptor(scoped_refptr<dbus::Bus> bus)
    : org::chromium::debugdAdaptor(this),
      dbus_object_(nullptr, bus, dbus::ObjectPath(kDebugdServicePath)) {
  battery_tool_ = std::make_unique<BatteryTool>();
  container_tool_ = std::make_unique<ContainerTool>();
  crash_sender_tool_ = std::make_unique<CrashSenderTool>();
  cups_tool_ = std::make_unique<CupsTool>();
  cros_healthd_tool_ = std::make_unique<CrosHealthdTool>();
  debug_logs_tool_ = std::make_unique<DebugLogsTool>(bus);
  debug_mode_tool_ = std::make_unique<DebugModeTool>(bus);
  dev_features_tool_wrapper_ =
      std::make_unique<RestrictedToolWrapper<DevFeaturesTool>>(bus);
  dmesg_tool_ = std::make_unique<DmesgTool>();
  ec_typec_tool_ = std::make_unique<EcTypeCTool>();
  example_tool_ = std::make_unique<ExampleTool>();
  icmp_tool_ = std::make_unique<ICMPTool>();
  ipaddrs_tool_ = std::make_unique<IpAddrsTool>();
  log_tool_ = std::make_unique<LogTool>(bus);
  memory_tool_ = std::make_unique<MemtesterTool>();
  netif_tool_ = std::make_unique<NetifTool>();
  network_status_tool_ = std::make_unique<NetworkStatusTool>();
  oom_adj_tool_ = std::make_unique<OomAdjTool>();
  packet_capture_tool_ = std::make_unique<PacketCaptureTool>();
  perf_tool_ = std::make_unique<PerfTool>();
  ping_tool_ = std::make_unique<PingTool>();
  probe_tool_ = std::make_unique<ProbeTool>();
  route_tool_ = std::make_unique<RouteTool>();
  shill_scripts_tool_ = std::make_unique<ShillScriptsTool>();
  storage_tool_ = std::make_unique<StorageTool>();
  swap_tool_ = std::make_unique<SwapTool>();
  sysrq_tool_ = std::make_unique<SysrqTool>();
  systrace_tool_ = std::make_unique<SystraceTool>();
  tracepath_tool_ = std::make_unique<TracePathTool>();
  u2f_tool_ = std::make_unique<U2fTool>();
  verify_ro_tool_ = std::make_unique<VerifyRoTool>();
  vm_plugin_dispatcher_tool_ = std::make_unique<SimpleServiceTool>(
      "vmplugin_dispatcher", bus,
      vm_tools::plugin_dispatcher::kVmPluginDispatcherServiceName,
      vm_tools::plugin_dispatcher::kVmPluginDispatcherServicePath);
  wifi_fw_dump_tool_ = std::make_unique<WifiFWDumpTool>();
  wifi_power_tool_ = std::make_unique<WifiPowerTool>();
  session_manager_proxy_ = std::make_unique<SessionManagerProxy>(bus);
  scheduler_configuration_tool_ =
      std::make_unique<SchedulerConfigurationTool>();
  if (dev_features_tool_wrapper_->restriction().InDevMode() &&
      base::PathExists(
          base::FilePath(debugd::kDevFeaturesChromeRemoteDebuggingFlagPath))) {
    session_manager_proxy_->EnableChromeRemoteDebugging();
  }
}

void DebugdDBusAdaptor::RegisterAsync(
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
  auto* my_interface = dbus_object_.AddOrGetInterface(kDebugdInterface);
  DCHECK(my_interface);
  my_interface->AddProperty(kCrashSenderTestMode, &crash_sender_test_mode_);
  crash_sender_test_mode_.SetUpdateCallback(
      base::Bind(&CrashSenderTool::OnTestModeChanged,
                 base::Unretained(crash_sender_tool_.get())));
  crash_sender_test_mode_.SetValue(false);
  crash_sender_test_mode_.SetAccessMode(
      brillo::dbus_utils::ExportedPropertyBase::Access::kReadWrite);
  RegisterWithDBusObject(&dbus_object_);
  dbus_object_.RegisterAsync(cb);
}

std::string DebugdDBusAdaptor::SetOomScoreAdj(
    const std::map<pid_t, int32_t>& scores) {
  return oom_adj_tool_->Set(scores);
}

bool DebugdDBusAdaptor::PingStart(brillo::ErrorPtr* error,
                                  const base::ScopedFD& outfd,
                                  const std::string& destination,
                                  const brillo::VariantDictionary& options,
                                  std::string* handle) {
  return ping_tool_->Start(outfd, destination, options, handle, error);
}

bool DebugdDBusAdaptor::PingStop(brillo::ErrorPtr* error,
                                 const std::string& handle) {
  return ping_tool_->Stop(handle, error);
}

std::string DebugdDBusAdaptor::TracePathStart(
    const base::ScopedFD& outfd,
    const std::string& destination,
    const brillo::VariantDictionary& options) {
  return tracepath_tool_->Start(outfd, destination, options);
}

bool DebugdDBusAdaptor::TracePathStop(brillo::ErrorPtr* error,
                                      const std::string& handle) {
  return tracepath_tool_->Stop(handle, error);
}

void DebugdDBusAdaptor::SystraceStart(const std::string& categories) {
  (void)systrace_tool_->Start(categories);
}

void DebugdDBusAdaptor::SystraceStop(const base::ScopedFD& outfd) {
  systrace_tool_->Stop(outfd);
}

std::string DebugdDBusAdaptor::SystraceStatus() {
  return systrace_tool_->Status();
}

std::vector<std::string> DebugdDBusAdaptor::GetIpAddresses(
    const brillo::VariantDictionary& options) {
  return ipaddrs_tool_->GetIpAddresses(options);
}

std::vector<std::string> DebugdDBusAdaptor::GetRoutes(
    const brillo::VariantDictionary& options) {
  return route_tool_->GetRoutes(options);
}

std::string DebugdDBusAdaptor::GetNetworkStatus() {
  return network_status_tool_->GetNetworkStatus();
}

bool DebugdDBusAdaptor::GetPerfOutput(brillo::ErrorPtr* error,
                                      uint32_t duration_sec,
                                      const std::vector<std::string>& perf_args,
                                      int32_t* status,
                                      std::vector<uint8_t>* perf_data,
                                      std::vector<uint8_t>* perf_stat) {
  return perf_tool_->GetPerfOutput(duration_sec, perf_args, perf_data,
                                   perf_stat, status, error);
}

bool DebugdDBusAdaptor::GetPerfOutputFd(
    brillo::ErrorPtr* error,
    uint32_t duration_sec,
    const std::vector<std::string>& perf_args,
    const base::ScopedFD& stdout_fd,
    uint64_t* session_id) {
  return perf_tool_->GetPerfOutputFd(duration_sec, perf_args, stdout_fd,
                                     session_id, error);
}

bool DebugdDBusAdaptor::StopPerf(brillo::ErrorPtr* error, uint64_t session_id) {
  return perf_tool_->StopPerf(session_id, error);
}

void DebugdDBusAdaptor::DumpDebugLogs(bool is_compressed,
                                      const base::ScopedFD& fd) {
  debug_logs_tool_->GetDebugLogs(is_compressed, fd);
}

void DebugdDBusAdaptor::SetDebugMode(const std::string& subsystem) {
  debug_mode_tool_->SetDebugMode(subsystem);
}

std::string DebugdDBusAdaptor::GetLog(const std::string& name) {
  return log_tool_->GetLog(name);
}

std::map<std::string, std::string> DebugdDBusAdaptor::GetAllLogs() {
  return log_tool_->GetAllLogs();
}

void DebugdDBusAdaptor::GetBigFeedbackLogs(const base::ScopedFD& fd,
                                           const std::string& username) {
  log_tool_->GetBigFeedbackLogs(fd, username);
}

void DebugdDBusAdaptor::BackupArcBugReport(const std::string& username) {
  log_tool_->BackupArcBugReport(username);
}

void DebugdDBusAdaptor::DeleteArcBugReportBackup(const std::string& username) {
  log_tool_->DeleteArcBugReportBackup(username);
}

void DebugdDBusAdaptor::GetJournalLog(const base::ScopedFD& fd) {
  log_tool_->GetJournalLog(fd);
}

std::string DebugdDBusAdaptor::GetExample() {
  return example_tool_->GetExample();
}

int32_t DebugdDBusAdaptor::CupsAddAutoConfiguredPrinter(
    const std::string& name, const std::string& uri) {
  return cups_tool_->AddAutoConfiguredPrinter(name, uri);
}

int32_t DebugdDBusAdaptor::CupsAddManuallyConfiguredPrinter(
    const std::string& name,
    const std::string& uri,
    const std::vector<uint8_t>& ppd_contents) {
  return cups_tool_->AddManuallyConfiguredPrinter(name, uri, ppd_contents);
}

bool DebugdDBusAdaptor::CupsRemovePrinter(const std::string& name) {
  return cups_tool_->RemovePrinter(name);
}

std::string DebugdDBusAdaptor::GetInterfaces() {
  return netif_tool_->GetInterfaces();
}

std::string DebugdDBusAdaptor::TestICMP(const std::string& host) {
  return icmp_tool_->TestICMP(host);
}

std::string DebugdDBusAdaptor::TestICMPWithOptions(
    const std::string& host,
    const std::map<std::string, std::string>& options) {
  return icmp_tool_->TestICMPWithOptions(host, options);
}

std::string DebugdDBusAdaptor::BatteryFirmware(const std::string& option) {
  return battery_tool_->BatteryFirmware(option);
}

std::string DebugdDBusAdaptor::Smartctl(const std::string& option) {
  return storage_tool_->Smartctl(option);
}

std::string DebugdDBusAdaptor::Mmc(const std::string& option) {
  return storage_tool_->Mmc(option);
}

std::string DebugdDBusAdaptor::Nvme(const std::string& option) {
  return storage_tool_->Nvme(option);
}

std::string DebugdDBusAdaptor::NvmeLog(const uint32_t page_id,
                                       const uint32_t length,
                                       bool raw_binary) {
  return storage_tool_->NvmeLog(page_id, length, raw_binary);
}

std::string DebugdDBusAdaptor::MemtesterStart(const base::ScopedFD& outfd,
                                              uint32_t memory) {
  return memory_tool_->Start(outfd, memory);
}

bool DebugdDBusAdaptor::MemtesterStop(brillo::ErrorPtr* error,
                                      const std::string& handle) {
  return memory_tool_->Stop(handle, error);
}

std::string DebugdDBusAdaptor::BadblocksStart(const base::ScopedFD& outfd) {
  return storage_tool_->Start(outfd);
}

bool DebugdDBusAdaptor::BadblocksStop(brillo::ErrorPtr* error,
                                      const std::string& handle) {
  return storage_tool_->Stop(handle, error);
}

bool DebugdDBusAdaptor::PacketCaptureStart(
    brillo::ErrorPtr* error,
    const base::ScopedFD& statfd,
    const base::ScopedFD& outfd,
    const brillo::VariantDictionary& options,
    std::string* handle) {
  return packet_capture_tool_->Start(statfd, outfd, options, handle, error);
}

bool DebugdDBusAdaptor::PacketCaptureStop(brillo::ErrorPtr* error,
                                          const std::string& handle) {
  return packet_capture_tool_->Stop(handle, error);
}

bool DebugdDBusAdaptor::LogKernelTaskStates(brillo::ErrorPtr* error) {
  return sysrq_tool_->LogKernelTaskStates(error);
}

void DebugdDBusAdaptor::UploadCrashes() {
  crash_sender_tool_->UploadCrashes();
}

bool DebugdDBusAdaptor::UploadSingleCrash(
    brillo::ErrorPtr* error,
    const std::vector<std::tuple<std::string, base::ScopedFD>>& in_files) {
  return crash_sender_tool_->UploadSingleCrash(in_files, error);
}

bool DebugdDBusAdaptor::RemoveRootfsVerification(brillo::ErrorPtr* error) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->RemoveRootfsVerification(error);
}

bool DebugdDBusAdaptor::EnableBootFromUsb(brillo::ErrorPtr* error) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->EnableBootFromUsb(error);
}

bool DebugdDBusAdaptor::EnableChromeRemoteDebugging(brillo::ErrorPtr* error) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->EnableChromeRemoteDebugging(error);
}

bool DebugdDBusAdaptor::ConfigureSshServer(brillo::ErrorPtr* error) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->ConfigureSshServer(error);
}

bool DebugdDBusAdaptor::SetUserPassword(brillo::ErrorPtr* error,
                                        const std::string& username,
                                        const std::string& password) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->SetUserPassword(username, password, error);
}

bool DebugdDBusAdaptor::EnableChromeDevFeatures(
    brillo::ErrorPtr* error, const std::string& root_password) {
  auto tool = dev_features_tool_wrapper_->GetTool(error);
  return tool && tool->EnableChromeDevFeatures(root_password, error);
}

bool DebugdDBusAdaptor::QueryDevFeatures(brillo::ErrorPtr* error,
                                         int32_t* features) {
  // Special case: if access fails here, we return DEV_FEATURES_DISABLED rather
  // than a D-Bus error. However, we still want to return an error if we can
  // access the tool but the tool execution fails.
  auto tool = dev_features_tool_wrapper_->GetTool(nullptr);
  if (!tool) {
    *features = DEV_FEATURES_DISABLED;
    return true;
  }

  return tool && tool->QueryDevFeatures(features, error);
}

bool DebugdDBusAdaptor::EnableDevCoredumpUpload(brillo::ErrorPtr* error) {
  if (base::PathExists(base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) {
    VLOG(1) << "Device coredump upload already enabled";
    return true;
  }
  if (base::WriteFile(base::FilePath(debugd::kDeviceCoredumpUploadFlagPath), "",
                      0) < 0) {
    DEBUGD_ADD_ERROR(error, kDevCoredumpDBusErrorString,
                     "Failed to write flag file.");
    PLOG(ERROR) << "Failed to write flag file.";
    return false;
  }
  return true;
}

bool DebugdDBusAdaptor::DisableDevCoredumpUpload(brillo::ErrorPtr* error) {
  if (!base::PathExists(
          base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) {
    VLOG(1) << "Device coredump upload already disabled";
    return true;
  }
  if (!base::DeleteFile(
          base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) {
    DEBUGD_ADD_ERROR(error, kDevCoredumpDBusErrorString,
                     "Failed to delete flag file.");
    PLOG(ERROR) << "Failed to delete flag file.";
    return false;
  }
  return true;
}

bool DebugdDBusAdaptor::KstaledSetRatio(brillo::ErrorPtr* error,
                                        uint8_t kstaled_ratio,
                                        bool* out_result) {
  *out_result = swap_tool_->KstaledSetRatio(error, kstaled_ratio);
  return *out_result;
}

std::string DebugdDBusAdaptor::SwapEnable(int32_t size, bool change_now) {
  return swap_tool_->SwapEnable(size, change_now);
}

std::string DebugdDBusAdaptor::SwapDisable(bool change_now) {
  return swap_tool_->SwapDisable(change_now);
}

std::string DebugdDBusAdaptor::SwapStartStop(bool on) {
  return swap_tool_->SwapStartStop(on);
}

std::string DebugdDBusAdaptor::SwapStatus() {
  return swap_tool_->SwapStatus();
}

std::string DebugdDBusAdaptor::SwapSetParameter(
    const std::string& parameter_name, int32_t parameter_value) {
  return swap_tool_->SwapSetParameter(parameter_name, parameter_value);
}

std::string DebugdDBusAdaptor::SetU2fFlags(const std::string& flags) {
  return u2f_tool_->SetFlags(flags);
}

std::string DebugdDBusAdaptor::GetU2fFlags() {
  return u2f_tool_->GetFlags();
}

void DebugdDBusAdaptor::ContainerStarted() {
  container_tool_->ContainerStarted();
}

void DebugdDBusAdaptor::ContainerStopped() {
  container_tool_->ContainerStopped();
}

std::string DebugdDBusAdaptor::WifiFWDump() {
  return wifi_fw_dump_tool_->WifiFWDump();
}

std::string DebugdDBusAdaptor::SetWifiPowerSave(bool enable) {
  return wifi_power_tool_->SetWifiPowerSave(enable);
}

std::string DebugdDBusAdaptor::GetWifiPowerSave() {
  return wifi_power_tool_->GetWifiPowerSave();
}

bool DebugdDBusAdaptor::RunShillScriptStart(
    brillo::ErrorPtr* error,
    const base::ScopedFD& outfd,
    const std::string& script,
    const std::vector<std::string>& script_args,
    std::string* handle) {
  return shill_scripts_tool_->Run(outfd, script, script_args, handle, error);
}

bool DebugdDBusAdaptor::RunShillScriptStop(brillo::ErrorPtr* error,
                                           const std::string& handle) {
  return shill_scripts_tool_->Stop(handle, error);
}

void DebugdDBusAdaptor::StartVmPluginDispatcher(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
    const std::string& in_user_id_hash,
    const std::string& in_lang) {
  // Perform basic validation of user ID hash.
  if (in_user_id_hash.length() != 40) {
    LOG(ERROR) << "Incorrect length of the user_id_hash (" << in_user_id_hash
               << ")";
    response->Return(false);
    return;
  }

  if (!base::ContainsOnlyChars(in_user_id_hash, "abcdef0123456789")) {
    LOG(ERROR) << "user_id_hash should only contain lower case hex digits ("
               << in_user_id_hash << ")";
    response->Return(false);
    return;
  }

  // Perform basic validation of the language string. We expect it to be
  // <language>[-<territory>].
  std::vector<base::StringPiece> chunks = base::SplitStringPiece(
      in_lang, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (chunks.size() < 1 || chunks.size() > 2 || chunks[0].empty()) {
    LOG(ERROR) << "malformed language argument (" << in_lang << ")";
    response->Return(false);
    return;
  }

  vm_plugin_dispatcher_tool_->StartService(
      {{"CROS_USER_ID_HASH", in_user_id_hash}, {"CROS_USER_UI_LANG", in_lang}},
      std::move(response));
}

void DebugdDBusAdaptor::StopVmPluginDispatcher() {
  vm_plugin_dispatcher_tool_->StopService();
}

bool DebugdDBusAdaptor::SetRlzPingSent(brillo::ErrorPtr* error) {
  std::string stderr;
  int result = ProcessWithOutput::RunProcess(
      "/usr/sbin/vpd",
      {"-i", "RW_VPD", "-s", std::string(kShouldSendRlzPingKey) + "=0"},
      true,     // requires root
      false,    // disable_sandbox
      nullptr,  // stdin
      nullptr,  // stdout
      &stderr, error);
  if (result != EXIT_SUCCESS) {
    std::string error_string =
        "Failed to set vpd key: " + std::string(kShouldSendRlzPingKey) +
        " with exit code: " + std::to_string(result) + " with error: " + stderr;
    DEBUGD_ADD_ERROR(error, kDevCoredumpDBusErrorString, error_string);
    PLOG(ERROR) << error_string;
    return false;
  }
  // Remove |kRlzEmbargoEndDateKey|, which is no longer useful after
  // |kShouldSendRlzPingKey| is updated.
  result = ProcessWithOutput::RunProcess(
      "/usr/sbin/vpd",
      {"-i", "RW_VPD", "-d", std::string(kRlzEmbargoEndDateKey)},
      true,     // requires root
      false,    // disable_sandbox
      nullptr,  // stdin
      nullptr,  // stdout
      &stderr, error);
  if (result != EXIT_SUCCESS) {
    std::string error_string =
        "Failed to delete vpd key: " + std::string(kRlzEmbargoEndDateKey) +
        " with exit code: " + std::to_string(result) + " with error: " + stderr;
    DEBUGD_ADD_ERROR(error, kDevCoredumpDBusErrorString, error_string);
    PLOG(ERROR) << error_string;
  }
  // Regenerate the vpd cache log.
  result = ProcessWithOutput::RunProcess("/usr/sbin/dump_vpd_log", {"--force"},
                                         true,     // requires root
                                         false,    // disable_sandbox
                                         nullptr,  // stdin
                                         nullptr,  // stdout
                                         &stderr, error);
  if (result != EXIT_SUCCESS) {
    std::string error_string =
        "Failed to dump vpd log with exit code: " + std::to_string(result) +
        " with error: " + stderr;
    DEBUGD_ADD_ERROR(error, kDevCoredumpDBusErrorString, error_string);
    PLOG(ERROR) << error_string;
  }
  // The client only cares if updating |kShouldSendRlzPingKey| is successful, so
  // returns true regardless of the result of removing |kRlzEmbargoEndDateKey|
  // or the cache log update.
  return true;
}

bool DebugdDBusAdaptor::UpdateAndVerifyFWOnUsbStart(
    brillo::ErrorPtr* error,
    const base::ScopedFD& outfd,
    const std::string& image_file,
    const std::string& ro_db_dir,
    std::string* handle) {
  return verify_ro_tool_->UpdateAndVerifyFWOnUsb(error, outfd, image_file,
                                                 ro_db_dir, handle);
}

bool DebugdDBusAdaptor::UpdateAndVerifyFWOnUsbStop(brillo::ErrorPtr* error,
                                                   const std::string& handle) {
  return verify_ro_tool_->Stop(handle, error);
}

bool DebugdDBusAdaptor::SetSchedulerConfiguration(brillo::ErrorPtr* error,
                                                  const std::string& policy,
                                                  bool* result) {
  uint32_t num_cores_disabled;
  return SetSchedulerConfigurationV2(error, policy, false /* lock_policy */,
                                     result, &num_cores_disabled);
}

bool DebugdDBusAdaptor::SetSchedulerConfigurationV2(
    brillo::ErrorPtr* error,
    const std::string& policy,
    bool lock_policy,
    bool* result,
    uint32_t* num_cores_disabled) {
  *result = scheduler_configuration_tool_->SetPolicy(policy, lock_policy, error,
                                                     num_cores_disabled);
  return *result;
}

bool DebugdDBusAdaptor::EvaluateProbeFunction(
    brillo::ErrorPtr* error,
    const std::string& probe_statement,
    brillo::dbus_utils::FileDescriptor* outfd) {
  return probe_tool_->EvaluateProbeFunction(error, probe_statement, outfd);
}

bool DebugdDBusAdaptor::CollectSmartBatteryMetric(
    brillo::ErrorPtr* error,
    const std::string& metric_name,
    std::string* output) {
  return cros_healthd_tool_->CollectSmartBatteryMetric(error, metric_name,
                                                       output);
}

std::string DebugdDBusAdaptor::EcGetInventory() {
  return ec_typec_tool_->GetInventory();
}

bool DebugdDBusAdaptor::CallDmesg(brillo::ErrorPtr* error,
                                  const brillo::VariantDictionary& options,
                                  std::string* output) {
  return dmesg_tool_->CallDmesg(options, error, output);
}

}  // namespace debugd
