1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef DBUS_OBJECT_PROXY_H_ 6 #define DBUS_OBJECT_PROXY_H_ 7 8 #include <dbus/dbus.h> 9 10 #include <map> 11 #include <memory> 12 #include <set> 13 #include <string> 14 #include <vector> 15 16 #include "base/callback.h" 17 #include "base/macros.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/strings/string_piece.h" 20 #include "base/time/time.h" 21 #include "dbus/dbus_export.h" 22 #include "dbus/object_path.h" 23 24 namespace base { 25 class TaskRunner; 26 } // namespace base 27 28 namespace dbus { 29 30 class Bus; 31 class ErrorResponse; 32 class MethodCall; 33 class Response; 34 class ScopedDBusError; 35 class Signal; 36 37 // ObjectProxy is used to communicate with remote objects, mainly for 38 // calling methods of these objects. 39 // 40 // ObjectProxy is a ref counted object, to ensure that |this| of the 41 // object is alive when callbacks referencing |this| are called; the 42 // bus always holds at least one of those references so object proxies 43 // always last as long as the bus that created them. 44 class CHROME_DBUS_EXPORT ObjectProxy 45 : public base::RefCountedThreadSafe<ObjectProxy> { 46 public: 47 // Client code should use Bus::GetObjectProxy() or 48 // Bus::GetObjectProxyWithOptions() instead of this constructor. 49 ObjectProxy(Bus* bus, 50 const std::string& service_name, 51 const ObjectPath& object_path, 52 int options); 53 54 // Options to be OR-ed together when calling Bus::GetObjectProxyWithOptions(). 55 // Set the IGNORE_SERVICE_UNKNOWN_ERRORS option to silence logging of 56 // org.freedesktop.DBus.Error.ServiceUnknown errors and 57 // org.freedesktop.DBus.Error.ObjectUnknown errors. 58 enum Options { 59 DEFAULT_OPTIONS = 0, 60 IGNORE_SERVICE_UNKNOWN_ERRORS = 1 << 0 61 }; 62 63 // Special timeout constants. 64 // 65 // The constants correspond to DBUS_TIMEOUT_USE_DEFAULT and 66 // DBUS_TIMEOUT_INFINITE. Here we use literal numbers instead of these 67 // macros as these aren't defined with D-Bus earlier than 1.4.12. 68 enum { 69 TIMEOUT_USE_DEFAULT = -1, 70 TIMEOUT_INFINITE = 0x7fffffff, 71 }; 72 73 // Called when an error response is returned or no response is returned. 74 // Used for CallMethodWithErrorCallback(). 75 using ErrorCallback = base::OnceCallback<void(ErrorResponse*)>; 76 77 // Called when the response is returned. Used for CallMethod(). 78 using ResponseCallback = base::OnceCallback<void(Response*)>; 79 80 // Called when the response is returned or an error occurs. Used for 81 // CallMethodWithErrorResponse(). 82 // Note that even in error case, ErrorResponse* may be nullptr. 83 // E.g. out-of-memory error is found in libdbus, or the connection of 84 // |bus_| is not yet established. 85 using ResponseOrErrorCallback = 86 base::OnceCallback<void(Response*, ErrorResponse*)>; 87 88 // Called when a signal is received. Signal* is the incoming signal. 89 using SignalCallback = base::Callback<void(Signal*)>; 90 91 // Called when NameOwnerChanged signal is received. 92 using NameOwnerChangedCallback = 93 base::Callback<void(const std::string& old_owner, 94 const std::string& new_owner)>; 95 96 // Called when the service becomes available. 97 using WaitForServiceToBeAvailableCallback = 98 base::OnceCallback<void(bool service_is_available)>; 99 100 // Called when the object proxy is connected to the signal. 101 // Parameters: 102 // - the interface name. 103 // - the signal name. 104 // - whether it was successful or not. 105 using OnConnectedCallback = 106 base::OnceCallback<void(const std::string&, const std::string&, bool)>; 107 108 // Calls the method of the remote object and blocks until the response 109 // is returned. Returns NULL on error with the error details specified 110 // in the |error| object. 111 // 112 // BLOCKING CALL. 113 virtual std::unique_ptr<Response> CallMethodAndBlockWithErrorDetails( 114 MethodCall* method_call, 115 int timeout_ms, 116 ScopedDBusError* error); 117 118 // Calls the method of the remote object and blocks until the response 119 // is returned. Returns NULL on error. 120 // 121 // BLOCKING CALL. 122 virtual std::unique_ptr<Response> CallMethodAndBlock(MethodCall* method_call, 123 int timeout_ms); 124 125 // Requests to call the method of the remote object. 126 // 127 // |callback| will be called in the origin thread, once the method call 128 // is complete. As it's called in the origin thread, |callback| can 129 // safely reference objects in the origin thread (i.e. UI thread in most 130 // cases). 131 // 132 // If the method call is successful, a pointer to Response object will 133 // be passed to the callback. If unsuccessful, nullptr will be passed to 134 // the callback. 135 // 136 // Must be called in the origin thread. 137 virtual void CallMethod(MethodCall* method_call, 138 int timeout_ms, 139 ResponseCallback callback); 140 141 // Requests to call the method of the remote object. 142 // 143 // This is almost as same as CallMethod() defined above. 144 // The difference is that, the |callback| can take ErrorResponse. 145 // In case of error, ErrorResponse object is passed to the |callback| 146 // if the remote object returned an error, or nullptr if a response was not 147 // received at all (e.g., D-Bus connection is not established). In either 148 // error case, Response* should be nullptr. 149 virtual void CallMethodWithErrorResponse(MethodCall* method_call, 150 int timeout_ms, 151 ResponseOrErrorCallback callback); 152 153 // DEPRECATED. Please use CallMethodWithErrorResponse() instead. 154 // TODO(hidehiko): Remove this when migration is done. 155 // Requests to call the method of the remote object. 156 // 157 // |callback| and |error_callback| will be called in the origin thread, once 158 // the method call is complete. As it's called in the origin thread, 159 // |callback| can safely reference objects in the origin thread (i.e. 160 // UI thread in most cases). 161 // 162 // If the method call is successful, |callback| will be invoked with a 163 // Response object. If unsuccessful, |error_callback| will be invoked with an 164 // ErrorResponse object (if the remote object returned an error) or nullptr 165 // (if a response was not received at all). 166 // 167 // Must be called in the origin thread. 168 virtual void CallMethodWithErrorCallback(MethodCall* method_call, 169 int timeout_ms, 170 ResponseCallback callback, 171 ErrorCallback error_callback); 172 173 // Requests to connect to the signal from the remote object. 174 // 175 // |signal_callback| will be called in the origin thread, when the 176 // signal is received from the remote object. As it's called in the 177 // origin thread, |signal_callback| can safely reference objects in the 178 // origin thread (i.e. UI thread in most cases). 179 // 180 // |on_connected_callback| is called when the object proxy is connected 181 // to the signal, or failed to be connected, in the origin thread. 182 // 183 // If a SignalCallback has already been registered for the given 184 // |interface_name| and |signal_name|, |signal_callback| will be 185 // added to the list of callbacks for |interface_name| and 186 // |signal_name|. 187 // 188 // Must be called in the origin thread. 189 virtual void ConnectToSignal(const std::string& interface_name, 190 const std::string& signal_name, 191 SignalCallback signal_callback, 192 OnConnectedCallback on_connected_callback); 193 194 // Sets a callback for "NameOwnerChanged" signal. The callback is called on 195 // the origin thread when D-Bus system sends "NameOwnerChanged" for the name 196 // represented by |service_name_|. 197 virtual void SetNameOwnerChangedCallback(NameOwnerChangedCallback callback); 198 199 // Registers |callback| to run when the service becomes available. If the 200 // service is already available, or if connecting to the name-owner-changed 201 // signal fails, |callback| will be run once asynchronously. Otherwise, 202 // |callback| will be run once in the future after the service becomes 203 // available. 204 virtual void WaitForServiceToBeAvailable( 205 WaitForServiceToBeAvailableCallback callback); 206 207 // Detaches from the remote object. The Bus object will take care of 208 // detaching so you don't have to do this manually. 209 // 210 // BLOCKING CALL. 211 virtual void Detach(); 212 object_path()213 const ObjectPath& object_path() const { return object_path_; } 214 215 protected: 216 // This is protected, so we can define sub classes. 217 virtual ~ObjectProxy(); 218 219 private: 220 friend class base::RefCountedThreadSafe<ObjectProxy>; 221 222 // Callback passed to CallMethod and its family should be deleted on the 223 // origin thread in any cases. This class manages the work. 224 class ReplyCallbackHolder { 225 public: 226 // Designed to be created on the origin thread. 227 // Both |origin_task_runner| and |callback| must not be null. 228 ReplyCallbackHolder(scoped_refptr<base::TaskRunner> origin_task_runner, 229 ResponseOrErrorCallback callback); 230 231 // This is movable to be bound to an OnceCallback. 232 ReplyCallbackHolder(ReplyCallbackHolder&& other); 233 234 // |callback_| needs to be destroyed on the origin thread. 235 // If this is not destroyed on non-origin thread, it PostTask()s the 236 // callback to the origin thread for destroying. 237 ~ReplyCallbackHolder(); 238 239 // Returns |callback_| with releasing its ownership. 240 // This must be called on the origin thread. 241 ResponseOrErrorCallback ReleaseCallback(); 242 243 private: 244 scoped_refptr<base::TaskRunner> origin_task_runner_; 245 ResponseOrErrorCallback callback_; 246 DISALLOW_COPY_AND_ASSIGN(ReplyCallbackHolder); 247 }; 248 249 // Starts the async method call. This is a helper function to implement 250 // CallMethod(). 251 void StartAsyncMethodCall(int timeout_ms, 252 DBusMessage* request_message, 253 ReplyCallbackHolder callback_holder, 254 base::TimeTicks start_time); 255 256 // Called when the pending call is complete. 257 void OnPendingCallIsComplete(ReplyCallbackHolder callback_holder, 258 base::TimeTicks start_time, 259 DBusPendingCall* pending_call); 260 261 // Runs the ResponseOrErrorCallback with the given response object. 262 void RunResponseOrErrorCallback(ReplyCallbackHolder callback_holderk, 263 base::TimeTicks start_time, 264 Response* response, 265 ErrorResponse* error_response); 266 267 // Connects to NameOwnerChanged signal. 268 bool ConnectToNameOwnerChangedSignal(); 269 270 // Helper function for ConnectToSignal(). 271 bool ConnectToSignalInternal(const std::string& interface_name, 272 const std::string& signal_name, 273 SignalCallback signal_callback); 274 275 // Helper function for WaitForServiceToBeAvailable(). 276 void WaitForServiceToBeAvailableInternal(); 277 278 // Handles the incoming request messages and dispatches to the signal 279 // callbacks. 280 DBusHandlerResult HandleMessage(DBusConnection* connection, 281 DBusMessage* raw_message); 282 283 // Runs the method. Helper function for HandleMessage(). 284 void RunMethod(base::TimeTicks start_time, 285 std::vector<SignalCallback> signal_callbacks, 286 Signal* signal); 287 288 // Redirects the function call to HandleMessage(). 289 static DBusHandlerResult HandleMessageThunk(DBusConnection* connection, 290 DBusMessage* raw_message, 291 void* user_data); 292 293 // Helper method for logging response errors appropriately. 294 void LogMethodCallFailure(const base::StringPiece& interface_name, 295 const base::StringPiece& method_name, 296 const base::StringPiece& error_name, 297 const base::StringPiece& error_message) const; 298 299 // Used as ResponseOrErrorCallback by CallMethod(). 300 // Logs error message, and drops |error_response| from the arguments to pass 301 // |response_callback|. 302 void OnCallMethod(const std::string& interface_name, 303 const std::string& method_name, 304 ResponseCallback response_callback, 305 Response* response, 306 ErrorResponse* error_response); 307 308 // Adds the match rule to the bus and associate the callback with the signal. 309 bool AddMatchRuleWithCallback(const std::string& match_rule, 310 const std::string& absolute_signal_name, 311 SignalCallback signal_callback); 312 313 // Adds the match rule to the bus so that HandleMessage can see the signal. 314 bool AddMatchRuleWithoutCallback(const std::string& match_rule, 315 const std::string& absolute_signal_name); 316 317 // Calls D-Bus's GetNameOwner method synchronously to update 318 // |service_name_owner_| with the current owner of |service_name_|. 319 // 320 // BLOCKING CALL. 321 void UpdateNameOwnerAndBlock(); 322 323 // Handles NameOwnerChanged signal from D-Bus's special message bus. 324 DBusHandlerResult HandleNameOwnerChanged( 325 std::unique_ptr<dbus::Signal> signal); 326 327 // Runs |name_owner_changed_callback_|. 328 void RunNameOwnerChangedCallback(const std::string& old_owner, 329 const std::string& new_owner); 330 331 // Runs |wait_for_service_to_be_available_callbacks_|. 332 void RunWaitForServiceToBeAvailableCallbacks(bool service_is_available); 333 334 scoped_refptr<Bus> bus_; 335 std::string service_name_; 336 ObjectPath object_path_; 337 338 // The method table where keys are absolute signal names (i.e. interface 339 // name + signal name), and values are lists of the corresponding callbacks. 340 using MethodTable = std::map<std::string, std::vector<SignalCallback>>; 341 MethodTable method_table_; 342 343 // The callback called when NameOwnerChanged signal is received. 344 NameOwnerChangedCallback name_owner_changed_callback_; 345 346 // Called when the service becomes available. 347 std::vector<WaitForServiceToBeAvailableCallback> 348 wait_for_service_to_be_available_callbacks_; 349 350 std::set<std::string> match_rules_; 351 352 const bool ignore_service_unknown_errors_; 353 354 // Known name owner of the well-known bus name represented by |service_name_|. 355 std::string service_name_owner_; 356 357 std::set<DBusPendingCall*> pending_calls_; 358 359 DISALLOW_COPY_AND_ASSIGN(ObjectProxy); 360 }; 361 362 } // namespace dbus 363 364 #endif // DBUS_OBJECT_PROXY_H_ 365