130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved.
230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be
330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// found in the LICENSE file.
430477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
5e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// This file provides internal implementation details of dispatching D-Bus
6e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// method calls to a D-Bus object methods by reading the expected parameter
7e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// values from D-Bus message buffer then invoking a native C++ callback with
8e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// those parameters passed in. If the callback returns a value, that value is
9e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// sent back to the caller of D-Bus method via the response message.
10e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
11e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// This is achieved by redirecting the parsing of parameter values from D-Bus
12e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// message buffer to DBusParamReader helper class.
13e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// DBusParamReader de-serializes the parameter values from the D-Bus message
14e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// and calls the provided native C++ callback with those arguments.
15e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// However it expects the callback with a simple signature like this:
16e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko//    void callback(Args...);
17f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The method handlers for DBusObject, on the other hand, have one of the
18f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// following signatures:
19f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    void handler(Args...);
20f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    ReturnType handler(Args...);
21f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    bool handler(ErrorPtr* error, Args...);
22a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko//    void handler(std::unique_ptr<DBusMethodResponse<T1, T2,...>>, Args...);
23e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko//
24e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// To make this all work, we craft a simple callback suitable for
25e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// DBusParamReader using a lambda in DBusInvoker::Invoke() and redirect the call
26e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// to the appropriate method handler using additional data captured by the
27e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// lambda object.
2830477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
29fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#ifndef LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_
30fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#define LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_
3130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
3230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <memory>
3330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <string>
3430477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <type_traits>
3530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
369ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/data_serialization.h>
379ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_method_response.h>
389ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_param_reader.h>
399ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_param_writer.h>
409ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/utils.h>
419ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/errors/error.h>
4230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <dbus/message.h>
4330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
449ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
4530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenkonamespace dbus_utils {
4630477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
47f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// This is an abstract base class to allow dispatching a native C++ callback
48f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// method when a corresponding D-Bus method is called.
49f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass DBusInterfaceMethodHandlerInterface {
50f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
51f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  virtual ~DBusInterfaceMethodHandlerInterface() = default;
52e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
53f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // Returns true if the method has been handled synchronously (whether or not
54f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // a success or error response message had been sent).
55f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  virtual void HandleMethod(dbus::MethodCall* method_call,
56f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                            ResponseSender sender) = 0;
57f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
58f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
59f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// This is a special implementation of DBusInterfaceMethodHandlerInterface for
60f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// extremely simple synchronous method handlers that cannot possibly fail
61f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// (that is, they do not send an error response).
62f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The handler is expected to take an arbitrary number of arguments of type
63f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant
64f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// reference) and outputs (passed in as pointers)...
65f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// It may also return a single value of type R (or could be a void function if
66f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// no return value is to be sent to the caller). If the handler has a return
67f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// value, then it cannot have any output parameters in its parameter list.
68f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be:
69f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    R(Args...)
70f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename R, typename... Args>
71f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandler
72f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
73f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
74f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
75f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // virtual function is invoked.
76f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  explicit SimpleDBusInterfaceMethodHandler(
77f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      const base::Callback<R(Args...)>& handler) : handler_(handler) {}
78f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
79f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
80f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                    ResponseSender sender) override {
815e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko    DBusMethodResponse<R> method_response(method_call, sender);
82f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    auto invoke_callback = [this, &method_response](const Args&... args) {
83f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      method_response.Return(handler_.Run(args...));
84e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    };
85e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
86e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    ErrorPtr param_reader_error;
87f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    dbus::MessageReader reader(method_call);
88f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    // The handler is expected a return value, don't allow output parameters.
8905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko    if (!DBusParamReader<false, Args...>::Invoke(
9005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
91f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      // Error parsing method arguments.
92f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
93e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    }
94f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  }
95f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
96f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private:
97f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // C++ callback to be called when a DBus method is dispatched.
98f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  base::Callback<R(Args...)> handler_;
99f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandler);
100f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
101e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
102f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// Specialization of SimpleDBusInterfaceMethodHandlerInterface for
103f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// R=void (methods with no return values).
104f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename... Args>
105f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandler<void, Args...>
106f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
107f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
108f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
109f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // virtual function is invoked.
110f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  explicit SimpleDBusInterfaceMethodHandler(
111f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      const base::Callback<void(Args...)>& handler) : handler_(handler) {}
112f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
113f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
114f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                    ResponseSender sender) override {
1155e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko    DBusMethodResponseBase method_response(method_call, sender);
116f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    auto invoke_callback = [this, &method_response](const Args&... args) {
117f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      handler_.Run(args...);
118f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      auto response = method_response.CreateCustomResponse();
119f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      dbus::MessageWriter writer(response.get());
120f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      DBusParamWriter::AppendDBusOutParams(&writer, args...);
121a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      method_response.SendRawResponse(std::move(response));
122f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    };
123e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
124f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    ErrorPtr param_reader_error;
125f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    dbus::MessageReader reader(method_call);
12605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko    if (!DBusParamReader<true, Args...>::Invoke(
12705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
128f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      // Error parsing method arguments.
129f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
130f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    }
13130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko  }
132f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
133f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private:
134f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // C++ callback to be called when a DBus method is dispatched.
135f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  base::Callback<void(Args...)> handler_;
136f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandler);
137f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
138f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
139f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface for simple
140f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// synchronous method handlers that may fail and return an error response
141f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// message.
142f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The handler is expected to take an arbitrary number of arguments of type
143f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant
144f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// reference) and outputs (passed in as pointers)...
145f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// In case of an error, the handler must return false and set the error details
146f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// into the |error| object provided.
147f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be:
148f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    bool(ErrorPtr*, Args...)
149f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename... Args>
150f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandlerWithError
151f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
152f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
153f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
154f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // virtual function is invoked.
155f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  explicit SimpleDBusInterfaceMethodHandlerWithError(
156f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      const base::Callback<bool(ErrorPtr*, Args...)>& handler)
15705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      : handler_(handler) {}
158f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
159f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
160f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                    ResponseSender sender) override {
1615e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko    DBusMethodResponseBase method_response(method_call, sender);
162f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    auto invoke_callback = [this, &method_response](const Args&... args) {
163f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      ErrorPtr error;
164f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      if (!handler_.Run(&error, args...)) {
165f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko        method_response.ReplyWithError(error.get());
166f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      } else {
167f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko        auto response = method_response.CreateCustomResponse();
168f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko        dbus::MessageWriter writer(response.get());
16990f61fd6ba7ccff59e28b09a3f75e8626b483934Alex Vakulenko        DBusParamWriter::AppendDBusOutParams(&writer, args...);
170a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko        method_response.SendRawResponse(std::move(response));
17190f61fd6ba7ccff59e28b09a3f75e8626b483934Alex Vakulenko      }
172e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    };
173e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
174e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    ErrorPtr param_reader_error;
175f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    dbus::MessageReader reader(method_call);
17605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko    if (!DBusParamReader<true, Args...>::Invoke(
17705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
178e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko      // Error parsing method arguments.
179f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
180e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    }
181f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  }
182e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
183f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private:
184f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // C++ callback to be called when a DBus method is dispatched.
185f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  base::Callback<bool(ErrorPtr*, Args...)> handler_;
186f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandlerWithError);
187f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
188e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
1893b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// An implementation of SimpleDBusInterfaceMethodHandlerWithErrorAndMessage
1903b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// which is almost identical to SimpleDBusInterfaceMethodHandlerWithError with
1913b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// the exception that the callback takes an additional parameter - raw D-Bus
1923b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// message used to invoke the method handler.
1933b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The handler is expected to take an arbitrary number of arguments of type
1943b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant
1953b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// reference) and outputs (passed in as pointers)...
1963b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// In case of an error, the handler must return false and set the error details
1973b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// into the |error| object provided.
1983b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The signature of the callback handler is expected to be:
1993b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko//    bool(ErrorPtr*, dbus::Message*, Args...)
2003b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkotemplate<typename... Args>
2013b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkoclass SimpleDBusInterfaceMethodHandlerWithErrorAndMessage
2023b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
2033b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko public:
2043b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
2053b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // virtual function is invoked.
2063b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  explicit SimpleDBusInterfaceMethodHandlerWithErrorAndMessage(
2073b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      const base::Callback<bool(ErrorPtr*, dbus::Message*, Args...)>& handler)
2083b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      : handler_(handler) {}
2093b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
2103b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
2113b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko                    ResponseSender sender) override {
2123b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    DBusMethodResponseBase method_response(method_call, sender);
2133b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    auto invoke_callback =
2143b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko        [this, method_call, &method_response](const Args&... args) {
2153b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      ErrorPtr error;
2163b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      if (!handler_.Run(&error, method_call, args...)) {
2173b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko        method_response.ReplyWithError(error.get());
2183b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      } else {
2193b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko        auto response = method_response.CreateCustomResponse();
2203b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko        dbus::MessageWriter writer(response.get());
2213b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko        DBusParamWriter::AppendDBusOutParams(&writer, args...);
222a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko        method_response.SendRawResponse(std::move(response));
2233b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      }
2243b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    };
2253b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
2263b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    ErrorPtr param_reader_error;
2273b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    dbus::MessageReader reader(method_call);
2283b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    if (!DBusParamReader<true, Args...>::Invoke(
2293b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
2303b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      // Error parsing method arguments.
2313b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
2323b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    }
2333b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  }
2343b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
2353b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko private:
2363b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // C++ callback to be called when a DBus method is dispatched.
2373b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  base::Callback<bool(ErrorPtr*, dbus::Message*, Args...)> handler_;
2383b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandlerWithErrorAndMessage);
2393b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko};
2403b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
241f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface for more generic
242f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// (and possibly asynchronous) method handlers. The handler is expected
243f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// to take an arbitrary number of input arguments of type |Args...| and send
244f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// the method call response (including a possible error response) using
245f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// the provided DBusMethodResponse object.
246f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be:
247a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko//    void(std::unique_ptr<DBusMethodResponse<RetTypes...>, Args...)
2485e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenkotemplate<typename Response, typename... Args>
249f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass DBusInterfaceMethodHandler : public DBusInterfaceMethodHandlerInterface {
250f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
251f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
252f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // virtual function is invoked.
253f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  explicit DBusInterfaceMethodHandler(
254a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      const base::Callback<void(std::unique_ptr<Response>, Args...)>& handler)
25505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      : handler_(handler) {}
256f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
257f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // This method forwards the call to |handler_| after extracting the required
258f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // arguments from the DBus message buffer specified in |method_call|.
259f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // The output parameters of |handler_| (if any) are sent back to the called.
260f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
261f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                    ResponseSender sender) override {
262f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    auto invoke_callback = [this, method_call, &sender](const Args&... args) {
263a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      std::unique_ptr<Response> response(new Response(method_call, sender));
264a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      handler_.Run(std::move(response), args...);
265e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    };
266e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko
267e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    ErrorPtr param_reader_error;
268f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    dbus::MessageReader reader(method_call);
26905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko    if (!DBusParamReader<false, Args...>::Invoke(
27005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
271f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      // Error parsing method arguments.
2725e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko      DBusMethodResponseBase method_response(method_call, sender);
273f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
274e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko    }
27530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko  }
276f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
277f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private:
278f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // C++ callback to be called when a D-Bus method is dispatched.
279a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko  base::Callback<void(std::unique_ptr<Response>, Args...)> handler_;
280f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
281f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  DISALLOW_COPY_AND_ASSIGN(DBusInterfaceMethodHandler);
282f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
283f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
2843b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// An implementation of DBusInterfaceMethodHandlerWithMessage which is almost
2853b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// identical to AddSimpleMethodHandlerWithError with the exception that the
2863b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// callback takes an additional parameter - raw D-Bus message.
2873b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The handler is expected to take an arbitrary number of input arguments of
2883b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// type |Args...| and send the method call response (including a possible error
2893b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// response) using the provided DBusMethodResponse object.
2903b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The signature of the callback handler is expected to be:
291a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko//    void(std::unique_ptr<DBusMethodResponse<RetTypes...>, dbus::Message*,
292a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko//         Args...);
2933b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkotemplate<typename Response, typename... Args>
2943b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkoclass DBusInterfaceMethodHandlerWithMessage
2953b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
2963b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko public:
2973b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
2983b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // virtual function is invoked.
2993b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  explicit DBusInterfaceMethodHandlerWithMessage(
300a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      const base::Callback<void(std::unique_ptr<Response>, dbus::Message*,
3013b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko                                Args...)>& handler)
3023b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      : handler_(handler) {}
3033b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
3043b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // This method forwards the call to |handler_| after extracting the required
3053b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // arguments from the DBus message buffer specified in |method_call|.
3063b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // The output parameters of |handler_| (if any) are sent back to the called.
3073b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
3083b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko                    ResponseSender sender) override {
3093b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    auto invoke_callback = [this, method_call, &sender](const Args&... args) {
310a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      std::unique_ptr<Response> response(new Response(method_call, sender));
311a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko      handler_.Run(std::move(response), method_call, args...);
3123b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    };
3133b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
3143b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    ErrorPtr param_reader_error;
3153b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    dbus::MessageReader reader(method_call);
3163b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    if (!DBusParamReader<false, Args...>::Invoke(
3173b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko            invoke_callback, &reader, &param_reader_error)) {
3183b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      // Error parsing method arguments.
3193b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      DBusMethodResponseBase method_response(method_call, sender);
3203b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko      method_response.ReplyWithError(param_reader_error.get());
3213b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko    }
3223b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  }
3233b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
3243b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko private:
3253b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  // C++ callback to be called when a D-Bus method is dispatched.
326a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko  base::Callback<void(std::unique_ptr<Response>,
327a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko                      dbus::Message*, Args...)> handler_;
3283b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
3293b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko  DISALLOW_COPY_AND_ASSIGN(DBusInterfaceMethodHandlerWithMessage);
3303b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko};
3313b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko
332f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface that has custom
333f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// processing of both input and output parameters. This class is used by
334f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// DBusObject::AddRawMethodHandler and expects the callback to be of the
335f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// following signature:
336f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko//    void(dbus::MethodCall*, ResponseSender)
337f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// It will be up to the callback to parse the input parameters from the
338f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// message buffer and construct the D-Bus Response object.
339f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass RawDBusInterfaceMethodHandler
340f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    : public DBusInterfaceMethodHandlerInterface {
341f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public:
342f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // A constructor that takes a |handler| to be called when HandleMethod()
343f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // virtual function is invoked.
344253b5b6d35d47ed6b58b0ca1042b7455b0e2fdb2Chih-Hung Hsieh  explicit RawDBusInterfaceMethodHandler(
345f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko      const base::Callback<void(dbus::MethodCall*, ResponseSender)>& handler)
34605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      : handler_(handler) {}
347f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
348f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  void HandleMethod(dbus::MethodCall* method_call,
349f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko                    ResponseSender sender) override {
350f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko    handler_.Run(method_call, sender);
351f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  }
352f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
353f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private:
354f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  // C++ callback to be called when a D-Bus method is dispatched.
355f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  base::Callback<void(dbus::MethodCall*, ResponseSender)> handler_;
356f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko
357f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko  DISALLOW_COPY_AND_ASSIGN(RawDBusInterfaceMethodHandler);
358f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko};
35930477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
36030477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko}  // namespace dbus_utils
3619ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
36230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko
363fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#endif  // LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_
364