| // 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 |