blob: ad02e4c836b3234eac385d69cdf1baf49729feaa [file] [log] [blame]
// 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/debug_daemon.h"
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus-c++/dbus.h>
#include "debugd/src/constants.h"
namespace debugd {
namespace {
const char kDevCoredumpDBusErrorString[] =
"org.chromium.debugd.error.DevCoreDump";
} // namespace
DebugDaemon::DebugDaemon(DBus::Connection* connection,
DBus::BusDispatcher* dispatcher)
: DBus::ObjectAdaptor(*connection, kDebugdServicePath),
dbus_(connection),
dispatcher_(dispatcher) {}
bool DebugDaemon::Init() {
battery_tool_ = new BatteryTool();
crash_sender_tool_ = new CrashSenderTool();
debug_logs_tool_ = new DebugLogsTool();
debug_mode_tool_ = new DebugModeTool(dbus_);
dev_features_tool_wrapper_ =
new RestrictedToolWrapper<DevFeaturesTool>(dbus_);
example_tool_ = new ExampleTool();
icmp_tool_ = new ICMPTool();
modem_status_tool_ = new ModemStatusTool();
netif_tool_ = new NetifTool();
network_status_tool_ = new NetworkStatusTool();
packet_capture_tool_ = new PacketCaptureTool();
ping_tool_ = new PingTool();
route_tool_ = new RouteTool();
sysrq_tool_ = new SysrqTool();
systrace_tool_ = new SystraceTool();
tracepath_tool_ = new TracePathTool();
log_tool_ = new LogTool();
perf_tool_ = new PerfTool();
storage_tool_ = new StorageTool();
memory_tool_ = new MemtesterTool();
wimax_status_tool_ = new WiMaxStatusTool();
if (!dbus_->acquire_name(kDebugdServiceName)) {
LOG(ERROR) << "Failed to acquire D-Bus name " << kDebugdServiceName;
return false;
}
session_manager_proxy_.reset(new SessionManagerProxy(dbus_));
if (dev_features_tool_wrapper_->restriction().InDevMode() &&
base::PathExists(
base::FilePath(debugd::kDevFeaturesChromeRemoteDebuggingFlagPath))) {
session_manager_proxy_->EnableChromeRemoteDebugging();
}
return true;
}
void DebugDaemon::Run() {
dispatcher_->enter();
while (1) {
dispatcher_->do_iteration();
}
// Unreachable.
dispatcher_->leave();
}
std::string DebugDaemon::PingStart(
const DBus::FileDescriptor& outfd,
const std::string& destination,
const std::map<std::string, DBus::Variant>& options,
DBus::Error& error) { // NOLINT
return ping_tool_->Start(outfd, destination, options, &error);
}
void DebugDaemon::PingStop(const std::string& handle,
DBus::Error& error) { // NOLINT
return ping_tool_->Stop(handle, &error);
}
std::string DebugDaemon::TracePathStart(
const DBus::FileDescriptor& outfd,
const std::string& destination,
const std::map<std::string, DBus::Variant>& options,
DBus::Error& error) { // NOLINT
return tracepath_tool_->Start(outfd, destination, options, &error);
}
void DebugDaemon::TracePathStop(const std::string& handle,
DBus::Error& error) { // NOLINT
return tracepath_tool_->Stop(handle, &error);
}
void DebugDaemon::SystraceStart(const std::string& categories,
DBus::Error& error) { // NOLINT
(void) systrace_tool_->Start(categories, &error);
}
void DebugDaemon::SystraceStop(const DBus::FileDescriptor& outfd,
DBus::Error& error) { // NOLINT
return systrace_tool_->Stop(outfd, &error);
}
std::string DebugDaemon::SystraceStatus(DBus::Error& error) { // NOLINT
return systrace_tool_->Status(&error);
}
std::vector<std::string> DebugDaemon::GetRoutes(
const std::map<std::string, DBus::Variant>& options,
DBus::Error& error) { // NOLINT
return route_tool_->GetRoutes(options, &error);
}
std::string DebugDaemon::GetModemStatus(DBus::Error& error) { // NOLINT
return modem_status_tool_->GetModemStatus(&error);
}
std::string DebugDaemon::RunModemCommand(const std::string& command,
DBus::Error& error) { // NOLINT
return modem_status_tool_->RunModemCommand(command);
}
std::string DebugDaemon::GetNetworkStatus(DBus::Error& error) { // NOLINT
return network_status_tool_->GetNetworkStatus(&error);
}
std::string DebugDaemon::GetWiMaxStatus(DBus::Error& error) { // NOLINT
return wimax_status_tool_->GetWiMaxStatus(&error);
}
void DebugDaemon::GetPerfOutput(
const 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,
DBus::Error& error) { // NOLINT
status = perf_tool_->GetPerfOutput(
duration_sec, perf_args, &perf_data, &perf_stat, &error);
}
void DebugDaemon::GetRandomPerfOutput(
const uint32_t& duration_sec,
int32_t& status,
std::vector<uint8_t>& perf_data,
std::vector<uint8_t>& perf_stat,
DBus::Error& error) { // NOLINT
status = perf_tool_->GetRandomPerfOutput(
duration_sec, &perf_data, &perf_stat, &error);
}
std::vector<uint8_t> DebugDaemon::GetRichPerfData(
const uint32_t& duration_sec, DBus::Error& error) { // NOLINT
return perf_tool_->GetRichPerfData(duration_sec, &error);
}
void DebugDaemon::GetDebugLogs(const DBus::FileDescriptor& fd,
DBus::Error& error) { // NOLINT
debug_logs_tool_->GetDebugLogs(true, // is_compressed,
fd,
&error);
}
void DebugDaemon::DumpDebugLogs(const bool& is_compressed,
const DBus::FileDescriptor& fd,
DBus::Error& error) { // NOLINT
debug_logs_tool_->GetDebugLogs(is_compressed, fd, &error);
}
void DebugDaemon::SetDebugMode(const std::string& subsystem,
DBus::Error& error) { // NOLINT
debug_mode_tool_->SetDebugMode(subsystem, &error);
}
std::string DebugDaemon::GetLog(const std::string& name,
DBus::Error& error) { // NOLINT
return log_tool_->GetLog(name, &error);
}
std::map<std::string, std::string> DebugDaemon::GetAllLogs(
DBus::Error& error) { // NOLINT
return log_tool_->GetAllLogs(dbus_, &error);
}
std::map<std::string, std::string> DebugDaemon::GetFeedbackLogs(
DBus::Error& error) { // NOLINT
return log_tool_->GetFeedbackLogs(dbus_, &error);
}
std::map<std::string, std::string> DebugDaemon::GetUserLogFiles(
DBus::Error& error) { // NOLINT
return log_tool_->GetUserLogFiles(&error);
}
std::string DebugDaemon::GetExample(DBus::Error& error) { // NOLINT
return example_tool_->GetExample(&error);
}
std::string DebugDaemon::GetInterfaces(DBus::Error& error) { // NOLINT
return netif_tool_->GetInterfaces(&error);
}
std::string DebugDaemon::TestICMP(const std::string& host,
DBus::Error& error) { // NOLINT
return icmp_tool_->TestICMP(host, &error);
}
std::string DebugDaemon::TestICMPWithOptions(
const std::string& host,
const std::map<std::string, std::string>& options,
DBus::Error& error) { // NOLINT
return icmp_tool_->TestICMPWithOptions(host, options, &error);
}
std::string DebugDaemon::BatteryFirmware(const std::string& option,
DBus::Error& error) { // NOLINT
return battery_tool_->BatteryFirmware(option, &error);
}
std::string DebugDaemon::Smartctl(const std::string& option,
DBus::Error& error) { // NOLINT
return storage_tool_->Smartctl(option, &error);
}
std::string DebugDaemon::MemtesterStart(const DBus::FileDescriptor& outfd,
const uint32_t& memory,
DBus::Error& error) { // NOLINT
return memory_tool_->Start(outfd, memory, &error);
}
void DebugDaemon::MemtesterStop(const std::string& handle,
DBus::Error& error) { // NOLINT
return memory_tool_->Stop(handle, &error);
}
std::string DebugDaemon::BadblocksStart(const DBus::FileDescriptor& outfd,
DBus::Error& error) { // NOLINT
return storage_tool_->Start(outfd, &error);
}
void DebugDaemon::BadblocksStop(const std::string& handle,
DBus::Error& error) { // NOLINT
return storage_tool_->Stop(handle, &error);
}
std::string DebugDaemon::PacketCaptureStart(
const DBus::FileDescriptor& statfd,
const DBus::FileDescriptor& outfd,
const std::map<std::string, DBus::Variant>& options,
DBus::Error& error) { // NOLINT
return packet_capture_tool_->Start(statfd, outfd, options, &error);
}
void DebugDaemon::PacketCaptureStop(const std::string& handle,
DBus::Error& error) { // NOLINT
return packet_capture_tool_->Stop(handle, &error);
}
void DebugDaemon::LogKernelTaskStates(DBus::Error& error) { // NOLINT
sysrq_tool_->LogKernelTaskStates(&error);
}
void DebugDaemon::UploadCrashes(DBus::Error& error) { // NOLINT
crash_sender_tool_->UploadCrashes(&error);
}
void DebugDaemon::RemoveRootfsVerification(DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[&error](DevFeaturesTool* tool) {
tool->RemoveRootfsVerification(&error);
},
&error);
}
void DebugDaemon::EnableBootFromUsb(DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[&error](DevFeaturesTool* tool) { tool->EnableBootFromUsb(&error); },
&error);
}
void DebugDaemon::EnableChromeRemoteDebugging(DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[&error](DevFeaturesTool* tool) {
tool->EnableChromeRemoteDebugging(&error);
},
&error);
}
void DebugDaemon::ConfigureSshServer(DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[&error](DevFeaturesTool* tool) { tool->ConfigureSshServer(&error); },
&error);
}
void DebugDaemon::SetUserPassword(const std::string& username,
const std::string& password,
DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[username, password, &error](DevFeaturesTool* tool) {
tool->SetUserPassword(username, password, &error);
},
&error);
}
void DebugDaemon::EnableChromeDevFeatures(const std::string& root_password,
DBus::Error& error) { // NOLINT
dev_features_tool_wrapper_->CallToolFunction(
[root_password, &error](DevFeaturesTool* tool) {
tool->EnableChromeDevFeatures(root_password, &error);
},
&error);
}
int32_t DebugDaemon::QueryDevFeatures(DBus::Error& error) { // NOLINT
// 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 so use error in the lambda.
int32_t features = DEV_FEATURES_DISABLED;
dev_features_tool_wrapper_->CallToolFunction(
[&features, &error](DevFeaturesTool* tool) {
features = tool->QueryDevFeatures(&error);
},
nullptr);
return features;
}
void DebugDaemon::EnableDevCoredumpUpload(DBus::Error& error) { // NOLINT
if (base::PathExists(
base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) {
VLOG(1) << "Device coredump upload already enabled";
return;
}
if (base::WriteFile(
base::FilePath(debugd::kDeviceCoredumpUploadFlagPath), "", 0) < 0) {
error.set(kDevCoredumpDBusErrorString, "Failed to write flag file.");
PLOG(ERROR) << "Failed to write flag file.";
return;
}
}
void DebugDaemon::DisableDevCoredumpUpload(DBus::Error& error) { // NOLINT
if (!base::PathExists(
base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) {
VLOG(1) << "Device coredump upload already disabled";
return;
}
if (!base::DeleteFile(
base::FilePath(debugd::kDeviceCoredumpUploadFlagPath), false)) {
error.set(kDevCoredumpDBusErrorString, "Failed to delete flag file.");
PLOG(ERROR) << "Failed to delete flag file.";
return;
}
}
} // namespace debugd