blob: 3684f145b242c7b3c3d8febfb1bd1b0632b6d2d0 [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_