blob: 42516d15c5feaef0edf0dcb720febedc7cbcb149 [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/values.h>
#include <dbus/runtime_probe/dbus-constants.h>
#include <google/protobuf/util/json_util.h>
#include "runtime_probe/daemon.h"
#include "runtime_probe/probe_config.h"
#include "runtime_probe/probe_config_loader_impl.h"
#include "runtime_probe/proto_bindings/runtime_probe.pb.h"
namespace runtime_probe {
using brillo::dbus_utils::AsyncEventSequencer;
using brillo::dbus_utils::DBusObject;
Daemon::Daemon(ProbeConfigLoader* config_loader)
: brillo::DBusServiceDaemon(kRuntimeProbeServiceName),
org::chromium::RuntimeProbeAdaptor(this),
config_loader_(config_loader) {}
int Daemon::OnInit() {
VLOG(1) << "Starting D-Bus service";
const auto exit_code = brillo::DBusServiceDaemon::OnInit();
return exit_code;
}
void Daemon::RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) {
DCHECK(!dbus_object_);
dbus_object_ = std::make_unique<brillo::dbus_utils::DBusObject>(
nullptr, bus_, dbus::ObjectPath(kRuntimeProbeServicePath));
RegisterWithDBusObject(dbus_object_.get());
dbus_object_->RegisterAsync(
sequencer->GetHandler("RegisterAsync() failed", true));
}
void Daemon::ProbeCategories(Daemon::DBusCallback<ProbeResult> cb,
const ProbeRequest& request) {
ProbeResult reply;
const auto probe_config_data = config_loader_->LoadDefault();
if (!probe_config_data) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INVALID);
cb->Return(reply);
return Quit();
}
LOG(INFO) << "Load probe config from: " << probe_config_data->path
<< " (checksum: " << probe_config_data->sha1_hash << ")";
reply.set_probe_config_checksum(probe_config_data->sha1_hash);
const auto probe_config = ProbeConfig::FromValue(probe_config_data->config);
if (!probe_config) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INCOMPLETE_PROBE_FUNCTION);
cb->Return(reply);
return Quit();
}
base::Value probe_result;
if (request.probe_default_category()) {
probe_result = probe_config->Eval();
} else {
// Convert the ProbeReuslt from enum into array of string.
std::vector<std::string> categories_to_probe;
const google::protobuf::EnumDescriptor* descriptor =
ProbeRequest_SupportCategory_descriptor();
for (int j = 0; j < request.categories_size(); j++)
categories_to_probe.push_back(
descriptor->FindValueByNumber(request.categories(j))->name());
probe_result = probe_config->Eval(categories_to_probe);
}
// TODO(itspeter): Report assigned but not in the probe config's category.
std::string output_js;
base::JSONWriter::Write(probe_result, &output_js);
DVLOG(3) << "Raw JSON probe result\n" << output_js;
// Convert JSON to Protocol Buffer.
auto options = google::protobuf::util::JsonParseOptions();
options.ignore_unknown_fields = true;
ProbeResult placeholder;
const auto json_parse_status = google::protobuf::util::JsonStringToMessage(
output_js, &placeholder, options);
reply.MergeFrom(placeholder);
VLOG(3) << "serialize JSON to Protobuf status: " << json_parse_status;
if (!json_parse_status.ok()) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_RESULT_INVALID);
}
cb->Return(reply);
return Quit();
}
void Daemon::GetKnownComponents(
Daemon::DBusCallback<GetKnownComponentsResult> cb,
const GetKnownComponentsRequest& request) {
GetKnownComponentsResult reply;
const auto probe_config_data = config_loader_->LoadDefault();
if (!probe_config_data) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INVALID);
cb->Return(reply);
return Quit();
}
const auto probe_config = ProbeConfig::FromValue(probe_config_data->config);
if (!probe_config) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INCOMPLETE_PROBE_FUNCTION);
cb->Return(reply);
return Quit();
}
std::string category_name =
ProbeRequest_SupportCategory_Name(request.category());
if (auto category = probe_config->GetComponentCategory(category_name);
category != nullptr) {
for (const auto& name : category->GetComponentNames()) {
reply.add_component_names(name);
}
}
cb->Return(reply);
return Quit();
}
} // namespace runtime_probe