blob: f50fe142beb5da3e8dc8c6276b0ed3afb19e4f93 [file] [log] [blame]
// Copyright (c) 2014 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.
// This file provides helper classes to allow all new DBus methods
// added to Cryptohome to use the "org.freedesktop.DBus.GLib.Async"
// annotation. By using the annotation, it makes the calls compatible
// with the new chrome/dbus/dbus.h mechanisms. It will make
// transitioning any new methods more straightforward and provide a means
// to transition existing methods in an incremental fashion.
// To transition a method, it will drop OUT_* types from its
// signature, and replace GError with DBusGMethodInvocation
// allowing the handling function to return immediately.
// Any method playing along will PostTask its work directly
// to the mount_thread_. Upon completion, the method implementation
// will then need to perform a PostTask-equivalent call back to
// the main/DBus thread to issue its reply -- be it success or
// failure. CryptohomeEventBase is used as a knock-off PostTask
// and the classes in this file provide the glue.
#include <memory>
#include <string>
#include <utility>
#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/callback.h>
#include <brillo/glib/dbus.h>
#include "cryptohome/cryptohome_event_source.h"
namespace cryptohome {
extern const char* kDBusErrorReplyEventType;
extern const char* kDBusBlobReplyEventType;
extern const char* kDBusReplyEventType;
struct GErrorDeleter {
inline void operator()(void* ptr) const {
class DBusErrorReply : public CryptohomeEventBase {
// Takes ownership of both pointers.
DBusErrorReply(DBusGMethodInvocation* context, GError* error);
virtual ~DBusErrorReply() {}
virtual const char* GetEventName() const { return kDBusErrorReplyEventType; }
virtual void Run() { dbus_g_method_return_error(context_, error_.get()); }
const GError& error() const { return *error_; }
// If this event is not serviced, the memory will be leaked.
DBusGMethodInvocation* context_;
std::unique_ptr<GError, GErrorDeleter> error_;
class DBusBlobReply : public CryptohomeEventBase {
// Ownership is taken for both pointers.
DBusBlobReply(DBusGMethodInvocation* context, std::string* reply);
virtual ~DBusBlobReply() {}
virtual const char* GetEventName() const { return kDBusBlobReplyEventType; }
virtual void Run() {
brillo::glib::ScopedArray tmp_array(g_array_new(FALSE, FALSE, 1));
g_array_append_vals(tmp_array.get(), reply_->c_str(), reply_->size());
dbus_g_method_return(context_, tmp_array.get());
const std::string& reply() const { return *reply_; }
// If this event is not serviced, the memory will be leaked.
DBusGMethodInvocation* context_;
std::unique_ptr<std::string> reply_;
// This class will allow glib-dbus method calls to be asynchronous.
// Note that this is only a temporary solution until glib-dbus is retired.
class DBusReply : public CryptohomeEventBase {
template <typename... Params>
DBusReply(base::OnceCallback<void(Params...)> cleanup_callback,
DBusGMethodInvocation* context,
Params... params) {
cleanup_callback_ = base::BindOnce(std::move(cleanup_callback), params...);
send_reply_ = base::BindOnce(
[](DBusGMethodInvocation* context_to_send, Params... params_to_send) {
dbus_g_method_return(context_to_send, params_to_send...);
context, params...);
// No output argument version
explicit DBusReply(DBusGMethodInvocation* context) {
cleanup_callback_ = base::DoNothing::Once();
send_reply_ = base::BindOnce(
[](DBusGMethodInvocation* context_to_send) {
virtual ~DBusReply() {}
virtual const char* GetEventName() const { return kDBusReplyEventType; }
virtual void Run() {
base::OnceClosure cleanup_callback_;
base::OnceClosure send_reply_;
} // namespace cryptohome