blob: 2a3a977170223af6a163c264d7b4225420a3a6b8 [file] [log] [blame]
// Copyright (c) 2010 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 "chromeos_imageburn.h"
#include <base/scoped_ptr.h>
#include <chromeos/dbus/abstract_dbus_service.h>
#include <chromeos/dbus/dbus.h>
#include <chromeos/dbus/service_constants.h>
#include "marshal.glibmarshal.h"
namespace chromeos {
class OpaqueBurnStatusConnection {
public:
typedef dbus::MonitorConnection<void (const char*, int64, int64)>*
ConnectionUpdateType;
typedef dbus::MonitorConnection<void (const char*, bool, const char*)>*
ConnectionFinishedType;
OpaqueBurnStatusConnection(const BurnMonitor& monitor,
const dbus::Proxy& burn_proxy,
void* object)
: monitor_(monitor),
object_(object),
burn_proxy_(burn_proxy),
updatedconnection_(NULL),
finishedconnection_(NULL) {
}
void FireEvent(BurnEventType evt, const char* path, int64 amount_burnt,
int64 total_size, const char* error) {
BurnStatus info;
info.target_path = path;
info.amount_burnt = amount_burnt;
info.total_size = total_size;
info.error = error;
monitor_(object_, info, evt);
}
static void Updated(void* object, const char* target_path,
int64 amount_burnt, int64 total_size) {
BurnStatusConnection self = static_cast<BurnStatusConnection>(object);
self->FireEvent(BURN_UPDATED, target_path, amount_burnt, total_size, "");
}
static void Finished(void* object, const char* target_path, bool success,
const char* error ) {
BurnStatusConnection self = static_cast<BurnStatusConnection>(object);
if(success) {
self->FireEvent(BURN_COMPLETE, target_path, 0, 0, "");
} else {
self->FireEvent(BURN_CANCELED, target_path, 0, 0, error);
}
}
ConnectionUpdateType& updateconnection() {
return updatedconnection_;
}
ConnectionFinishedType& finishedconnection() {
return finishedconnection_;
}
void StartBurn(const char* from_path, const char* to_path) {
glib::ScopedError error;
if (!::dbus_g_proxy_call(burn_proxy_.gproxy(),
imageburn::kBurnImage,
&Resetter(&error).lvalue(),
G_TYPE_STRING, from_path,
G_TYPE_STRING, to_path,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
LOG(WARNING) << "Burn operation unable to start: "
<< (error->message ? error->message : "Unknown Error.");
Finished(this, to_path, false, error->message);
}
}
private:
BurnMonitor monitor_;
void* object_;
dbus::Proxy burn_proxy_;
ConnectionUpdateType updatedconnection_;
ConnectionFinishedType finishedconnection_;
};
extern "C"
BurnStatusConnection ChromeOSMonitorBurnStatus(BurnMonitor monitor,
void* object) {
dbus::BusConnection bus = dbus::GetSystemBusConnection();
dbus::Proxy burn_proxy(bus,
imageburn::kImageBurnServiceName,
imageburn::kImageBurnServicePath,
imageburn::kImageBurnServiceInterface);
BurnStatusConnection result =
new OpaqueBurnStatusConnection(monitor, burn_proxy, object);
typedef dbus::MonitorConnection<void (const char*, int64, int64)>
ConnectionUpdateType;
typedef dbus::MonitorConnection<void (const char*, bool, const char*)>
ConnectionFinishedType;
// Adding update signal and connection.
::dbus_g_object_register_marshaller(marshal_VOID__STRING_INT64_INT64,
G_TYPE_NONE,
G_TYPE_STRING,
G_TYPE_INT64,
G_TYPE_INT64,
G_TYPE_INVALID);
::dbus_g_proxy_add_signal(burn_proxy.gproxy(),
imageburn::kSignalBurnUpdateName,
G_TYPE_STRING,
G_TYPE_INT64,
G_TYPE_INT64,
G_TYPE_INVALID);
ConnectionUpdateType* updated = new ConnectionUpdateType(burn_proxy,
imageburn::kSignalBurnUpdateName, &OpaqueBurnStatusConnection::Updated,
result);
::dbus_g_proxy_connect_signal(burn_proxy.gproxy(),
imageburn::kSignalBurnUpdateName,
G_CALLBACK(&ConnectionUpdateType::Run),
updated, NULL);
result->updateconnection() = updated;
// Adding end signal and connection.
::dbus_g_object_register_marshaller(marshal_VOID__STRING_BOOLEAN_STRING,
G_TYPE_NONE,
G_TYPE_STRING,
G_TYPE_BOOLEAN,
G_TYPE_STRING,
G_TYPE_INVALID);
::dbus_g_proxy_add_signal(burn_proxy.gproxy(),
imageburn::kSignalBurnFinishedName,
G_TYPE_STRING,
G_TYPE_BOOLEAN,
G_TYPE_STRING,
G_TYPE_INVALID);
ConnectionFinishedType* finished = new ConnectionFinishedType(burn_proxy,
imageburn::kSignalBurnFinishedName,
&OpaqueBurnStatusConnection::Finished, result);
::dbus_g_proxy_connect_signal(burn_proxy.gproxy(),
imageburn::kSignalBurnFinishedName,
G_CALLBACK(&ConnectionFinishedType::Run),
finished, NULL);
result->finishedconnection() = finished;
return result;
}
extern "C"
void ChromeOSDisconnectBurnStatus(BurnStatusConnection connection) {
dbus::Disconnect(connection->updateconnection());
dbus::Disconnect(connection->finishedconnection());
delete connection;
}
extern "C"
void ChromeOSStartBurn(const char* from_path, const char* to_path,
BurnStatusConnection connection) {
connection->StartBurn(from_path, to_path);
}
} // namespace chromeos