blob: 877cbbec335707fab95d65128ff43cb9ac21f6d9 [file] [log] [blame]
// Copyright (c) 2011 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 "image-burner/image_burn_service.h"
#include <ctype.h>
#include <glib.h>
#include <string>
#include <base/logging.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "image-burner/image_burner.h"
namespace imageburn {
#include "bindings/image_burner.dbusserver.h" // NOLINT(build/include_alpha)
namespace {
// Update signal is emitted only when there is at least
// |kProgressSignalInterval| bytes progress.
const int kProgressSignalInterval = 100 * 1024; // 100 KB
} // namespace
ImageBurnService::ImageBurnService(BurnerImpl* burner_impl)
: image_burner_(),
main_loop_(NULL),
amount_burnt_for_next_signal_(0),
burning_(false),
burner_impl_(burner_impl) {
LOG(INFO) << "Image Burn Service created";
}
ImageBurnService::~ImageBurnService() {
Cleanup();
}
const char* ImageBurnService::service_name() const {
return kImageBurnServiceName;
}
const char* ImageBurnService::service_path() const {
return kImageBurnServicePath;
}
const char* ImageBurnService::service_interface() const {
return kImageBurnServiceInterface;
}
GObject* ImageBurnService::service_object() const {
return G_OBJECT(image_burner_);
}
bool ImageBurnService::Initialize() {
// Install the type-info for the service with dbus.
dbus_g_object_type_install_info(image_burner_get_type(),
&dbus_glib_image_burner_object_info);
signals_[kSignalBurnUpdate] =
g_signal_new(kSignalBurnUpdateName, image_burner_get_type(),
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, nullptr, G_TYPE_NONE, 3,
G_TYPE_STRING, G_TYPE_INT64, G_TYPE_INT64);
signals_[kSignalBurnFinished] =
g_signal_new(kSignalBurnFinishedName, image_burner_get_type(),
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, nullptr, G_TYPE_NONE, 3,
G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING);
return Reset();
}
bool ImageBurnService::Reset() {
LOG(INFO) << "Reseting Image Burn Service";
Cleanup();
image_burner_ = reinterpret_cast<ImageBurner*>(
g_object_new(image_burner_get_type(), NULL));
// Allow references to this instance.
image_burner_->service = this;
main_loop_ = g_main_loop_new(NULL, false);
if (!main_loop_) {
LOG(ERROR) << "Failed to create main loop for Image Burn Service";
return false;
}
return true;
}
bool ImageBurnService::Shutdown() {
return brillo::dbus::AbstractDbusService::Shutdown();
}
gboolean ImageBurnService::BurnImageAsync(gchar* from_path,
gchar* to_path,
DBusGMethodInvocation* context) {
std::string error_str;
bool success = true;
if (!burner_impl_) {
error_str = "Burner not set";
success = false;
}
if (!burning_) {
burning_ = true;
} else {
error_str = "Another burn in progress.";
success = false;
}
if (success) {
dbus_g_method_return(context);
amount_burnt_for_next_signal_ = 0;
burner_impl_->BurnImage(from_path, to_path);
burning_ = false;
} else {
GError* error = NULL;
SetError(error_str, &error);
dbus_g_method_return_error(context, error);
g_error_free(error);
return false;
}
return true;
}
void ImageBurnService::Cleanup() {
if (main_loop_) {
g_main_loop_unref(main_loop_);
main_loop_ = NULL;
}
if (image_burner_) {
g_object_unref(image_burner_);
image_burner_ = NULL;
}
}
void ImageBurnService::SendFinishedSignal(const char* target_path,
bool success,
const char* error_message) {
if (!image_burner_) {
LOG(WARNING) << "Finished signal not sent due to sender not being "
<< "initialized";
return;
}
g_signal_emit(image_burner_, signals_[kSignalBurnFinished], 0, target_path,
success, error_message);
}
void ImageBurnService::SendProgressSignal(int64_t amount_burnt,
int64_t total_size,
const char* target_path) {
if (!image_burner_) {
LOG(WARNING) << "Progress signal not sent due to sender not being "
<< "initialized";
return;
}
// Send signal only when there is at least |kProgressSignalInterval| bytes
// progress.
if (amount_burnt >= amount_burnt_for_next_signal_) {
g_signal_emit(image_burner_, signals_[kSignalBurnUpdate], 0, target_path,
amount_burnt, total_size);
amount_burnt_for_next_signal_ = amount_burnt + kProgressSignalInterval;
}
}
void ImageBurnService::SetError(const std::string& message, GError** error) {
g_set_error_literal(error, g_quark_from_static_string("image-burn-quark"), 0,
message.c_str());
}
} // namespace imageburn