blob: 1ad84a43c0360b649ebc869a9fa07453aab00a13 [file] [log] [blame]
// Copyright (c) 2012 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.
#ifndef SHILL_DBUS_ADAPTOR_H_
#define SHILL_DBUS_ADAPTOR_H_
#include <map>
#include <string>
#include <vector>
#include <base/callback.h>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <dbus-c++/dbus.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "shill/accessor_interface.h"
#include "shill/adaptor_interfaces.h"
#include "shill/callbacks.h"
#include "shill/error.h"
namespace shill {
#define SHILL_INTERFACE "org.chromium.flimflam"
#define SHILL_PATH "/org/chromium/flimflam"
class KeyValueStore;
class PropertyStore;
// Superclass for all DBus-backed Adaptor objects
class DBusAdaptor : public DBus::ObjectAdaptor,
public DBus::IntrospectableAdaptor,
public base::SupportsWeakPtr<DBusAdaptor> {
public:
static const char kNullPath[];
DBusAdaptor(DBus::Connection* conn, const std::string& object_path);
~DBusAdaptor() override;
// Set the property with |name| through |store|. Returns true if and
// only if the property was changed. Updates |error| if a) an error
// was encountered, and b) |error| is non-NULL. Otherwise, |error| is
// unchanged.
static bool SetProperty(PropertyStore* store,
const std::string& name,
const ::DBus::Variant& value,
::DBus::Error* error);
static bool GetProperties(const PropertyStore& store,
std::map<std::string, ::DBus::Variant>* out,
::DBus::Error* error);
// Look for a property with |name| in |store|. If found, reset the
// property to its "factory" value. If the property can not be
// found, or if it can not be cleared (e.g., because it is
// read-only), set |error| accordingly.
//
// Returns true if the property was found and cleared; returns false
// otherwise.
static bool ClearProperty(PropertyStore* store,
const std::string& name,
::DBus::Error* error);
static void ArgsToKeyValueStore(
const std::map<std::string, ::DBus::Variant>& args,
KeyValueStore* out,
Error* error);
static ::DBus::Variant BoolToVariant(bool value);
static ::DBus::Variant ByteArraysToVariant(const ByteArrays& value);
static ::DBus::Variant ByteToVariant(uint8_t value);
static ::DBus::Variant Int16ToVariant(int16_t value);
static ::DBus::Variant Int32ToVariant(int32_t value);
static ::DBus::Variant KeyValueStoreToVariant(const KeyValueStore& value);
static ::DBus::Variant PathToVariant(const ::DBus::Path& value);
static ::DBus::Variant PathsToVariant(const std::vector<::DBus::Path>& value);
static ::DBus::Variant StringToVariant(const std::string& value);
static ::DBus::Variant StringmapToVariant(const Stringmap& value);
static ::DBus::Variant StringmapsToVariant(const Stringmaps& value);
static ::DBus::Variant StringsToVariant(const Strings& value);
static ::DBus::Variant Uint16ToVariant(uint16_t value);
static ::DBus::Variant Uint16sToVariant(const Uint16s& value);
static ::DBus::Variant Uint32ToVariant(uint32_t value);
static ::DBus::Variant Uint64ToVariant(uint64_t value);
static bool IsBool(::DBus::Signature signature);
static bool IsByte(::DBus::Signature signature);
static bool IsByteArrays(::DBus::Signature signature);
static bool IsInt16(::DBus::Signature signature);
static bool IsInt32(::DBus::Signature signature);
static bool IsPath(::DBus::Signature signature);
static bool IsPaths(::DBus::Signature signature);
static bool IsString(::DBus::Signature signature);
static bool IsStringmap(::DBus::Signature signature);
static bool IsStringmaps(::DBus::Signature signature);
static bool IsStrings(::DBus::Signature signature);
static bool IsUint16(::DBus::Signature signature);
static bool IsUint16s(::DBus::Signature signature);
static bool IsUint32(::DBus::Signature signature);
static bool IsUint64(::DBus::Signature signature);
static bool IsKeyValueStore(::DBus::Signature signature);
protected:
FRIEND_TEST(DBusAdaptorTest, SanitizePathElement);
ResultCallback GetMethodReplyCallback(const DBus::Tag* tag);
// It would be nice if these two methods could be templated. Unfortunately,
// attempts to do so will trigger some fairly esoteric warnings from the
// base library.
ResultStringCallback GetStringMethodReplyCallback(const DBus::Tag* tag);
ResultBoolCallback GetBoolMethodReplyCallback(const DBus::Tag* tag);
// Adaptors call this method just before returning. If |error|
// indicates that the operation has completed, with no asynchronously
// delivered result expected, then a DBus method reply is immediately
// sent to the client that initiated the method invocation. Otherwise,
// the operation is ongoing, and the result will be sent to the client
// when the operation completes at some later time.
//
// Adaptors should always construct an Error initialized to the value
// Error::kOperationInitiated. A pointer to this Error is passed down
// through the call stack. Any layer that determines that the operation
// has completed, either because of a failure that prevents carrying it
// out, or because it was possible to complete it without sending a request
// to an external server, should call error.Reset() to indicate success,
// or to some error type to reflect the kind of failure that occurred.
// Otherwise, they should leave the Error alone.
//
// The general structure of an adaptor method is
//
// void XXXXDBusAdaptor::SomeMethod(<args...>, DBus::Error& error) {
// Error e(Error::kOperationInitiated);
// DBus::Tag* tag = new DBus::Tag();
// xxxx_->SomeMethod(<args...>, &e, GetMethodReplyCallback(tag));
// ReturnResultOrDefer(tag, e, &error);
// }
//
void ReturnResultOrDefer(const DBus::Tag* tag,
const Error& error,
DBus::Error* dberror);
// Returns an object path fragment that conforms to D-Bus specifications.
static std::string SanitizePathElement(const std::string& object_path);
private:
void MethodReplyCallback(const DBus::Tag* tag, const Error& error);
void StringMethodReplyCallback(const DBus::Tag* tag, const Error& error,
const std::string& returned);
void BoolMethodReplyCallback(const DBus::Tag* tag, const Error& error,
bool returned);
template<typename T>
void TypedMethodReplyCallback(const DBus::Tag* tag, const Error& error,
const T& returned);
void DeferReply(const DBus::Tag* tag);
void ReplyNow(const DBus::Tag* tag);
template <typename T>
void TypedReplyNow(const DBus::Tag* tag, const T& value);
void ReplyNowWithError(const DBus::Tag* tag, const DBus::Error& error);
DISALLOW_COPY_AND_ASSIGN(DBusAdaptor);
};
} // namespace shill
#endif // SHILL_DBUS_ADAPTOR_H_