1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef SHILL_DBUS_CHROMEOS_DBUS_ADAPTOR_H_
18 #define SHILL_DBUS_CHROMEOS_DBUS_ADAPTOR_H_
19 
20 #include <string>
21 
22 #include <base/callback.h>
23 #include <base/macros.h>
24 #include <base/memory/weak_ptr.h>
25 #include <brillo/dbus/dbus_object.h>
26 #include <brillo/dbus/exported_object_manager.h>
27 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
28 
29 #include "shill/callbacks.h"
30 #include "shill/error.h"
31 #include "shill/property_store.h"
32 
33 namespace shill {
34 
35 template<typename... Types>
36 using DBusMethodResponsePtr =
37     std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<Types...>>;
38 
39 // Superclass for all DBus-backed Adaptor objects
40 class ChromeosDBusAdaptor : public base::SupportsWeakPtr<ChromeosDBusAdaptor> {
41  public:
42   static const char kNullPath[];
43 
44   ChromeosDBusAdaptor(
45       const scoped_refptr<dbus::Bus>& bus,
46       const std::string& object_path);
47   ~ChromeosDBusAdaptor();
48 
dbus_path()49   const dbus::ObjectPath& dbus_path() const { return dbus_path_; }
50 
51  protected:
52   FRIEND_TEST(ChromeosDBusAdaptorTest, SanitizePathElement);
53 
54   // Callback to wrap around DBus method response.
55   ResultCallback GetMethodReplyCallback(DBusMethodResponsePtr<> response);
56 
57   // It would be nice if these two methods could be templated.  Unfortunately,
58   // attempts to do so will trigger some fairly esoteric warnings from the
59   // base library.
60   ResultStringCallback GetStringMethodReplyCallback(
61       DBusMethodResponsePtr<std::string> response);
62   ResultBoolCallback GetBoolMethodReplyCallback(
63       DBusMethodResponsePtr<bool> response);
64 
65   // Adaptors call this method just before returning. If |error|
66   // indicates that the operation has completed, with no asynchronously
67   // delivered result expected, then a DBus method reply is immediately
68   // sent to the client that initiated the method invocation. Otherwise,
69   // the operation is ongoing, and the result will be sent to the client
70   // when the operation completes at some later time.
71   //
72   // Adaptors should always construct an Error initialized to the value
73   // Error::kOperationInitiated. A pointer to this Error is passed down
74   // through the call stack. Any layer that determines that the operation
75   // has completed, either because of a failure that prevents carrying it
76   // out, or because it was possible to complete it without sending a request
77   // to an external server, should call error.Reset() to indicate success,
78   // or to some error type to reflect the kind of failure that occurred.
79   // Otherwise, they should leave the Error alone.
80   //
81   // The general structure of an adaptor method is
82   //
83   // void XXXXDBusAdaptor::SomeMethod(<args...>, DBusMethodResponsePtr<> resp) {
84   //   Error e(Error::kOperationInitiated);
85   //   ResultCallback callback = GetMethodReplyCallback(resp);
86   //   xxxx_->SomeMethod(<args...>, &e, callback);
87   //   ReturnResultOrDefer(callback, e);
88   // }
89   //
90   void ReturnResultOrDefer(const ResultCallback& callback, const Error& error);
91 
dbus_object()92   brillo::dbus_utils::DBusObject* dbus_object() const {
93     return dbus_object_.get();
94   }
95 
96   // Set the property with |name| through |store|. Returns true if and
97   // only if the property was changed. Updates |error| if a) an error
98   // was encountered, and b) |error| is non-NULL. Otherwise, |error| is
99   // unchanged.
100   static bool SetProperty(PropertyStore* store,
101                           const std::string& name,
102                           const brillo::Any& value,
103                           brillo::ErrorPtr* error);
104   static bool GetProperties(const PropertyStore& store,
105                             brillo::VariantDictionary* out_properties,
106                             brillo::ErrorPtr* error);
107   // Look for a property with |name| in |store|. If found, reset the
108   // property to its "factory" value. If the property can not be
109   // found, or if it can not be cleared (e.g., because it is
110   // read-only), set |error| accordingly.
111   //
112   // Returns true if the property was found and cleared; returns false
113   // otherwise.
114   static bool ClearProperty(PropertyStore* store,
115                             const std::string& name,
116                             brillo::ErrorPtr* error);
117 
118   // Returns an object path fragment that conforms to D-Bus specifications.
119   static std::string SanitizePathElement(const std::string& object_path);
120 
121  private:
122   void MethodReplyCallback(DBusMethodResponsePtr<> response,
123                            const Error& error);
124 
125   void StringMethodReplyCallback(DBusMethodResponsePtr<std::string> response,
126                                  const Error& error,
127                                  const std::string& returned);
128   void BoolMethodReplyCallback(DBusMethodResponsePtr<bool> response,
129                                const Error& error,
130                                bool returned);
131   template<typename T>
132   void TypedMethodReplyCallback(DBusMethodResponsePtr<T> response,
133                                 const Error& error,
134                                 const T& returned);
135 
136   dbus::ObjectPath dbus_path_;
137   std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
138 
139   DISALLOW_COPY_AND_ASSIGN(ChromeosDBusAdaptor);
140 };
141 
142 }  // namespace shill
143 
144 #endif  // SHILL_DBUS_CHROMEOS_DBUS_ADAPTOR_H_
145