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_EXPORTED_OBJECT_H_ 6 #define DBUS_EXPORTED_OBJECT_H_ 7 8 #include <dbus/dbus.h> 9 10 #include <map> 11 #include <memory> 12 #include <string> 13 #include <utility> 14 15 #include "base/callback.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/synchronization/waitable_event.h" 18 #include "base/threading/platform_thread.h" 19 #include "base/time/time.h" 20 #include "dbus/dbus_export.h" 21 #include "dbus/object_path.h" 22 23 namespace dbus { 24 25 class Bus; 26 class MethodCall; 27 class Response; 28 class Signal; 29 30 // ExportedObject is used to export objects and methods to other D-Bus 31 // clients. 32 // 33 // ExportedObject is a ref counted object, to ensure that |this| of the 34 // object is alive when callbacks referencing |this| are called. 35 class CHROME_DBUS_EXPORT ExportedObject 36 : public base::RefCountedThreadSafe<ExportedObject> { 37 public: 38 // Client code should use Bus::GetExportedObject() instead of this 39 // constructor. 40 ExportedObject(Bus* bus, const ObjectPath& object_path); 41 42 // Called to send a response from an exported method. |response| is the 43 // response message. Callers should pass NULL in the event of an error that 44 // prevents the sending of a response. 45 typedef base::Callback<void(std::unique_ptr<Response> response)> 46 ResponseSender; 47 48 // Called when an exported method is called. |method_call| is the request 49 // message. |sender| is the callback that's used to send a response. 50 // 51 // |method_call| is owned by ExportedObject, hence client code should not 52 // delete |method_call|. 53 typedef base::Callback<void (MethodCall* method_call, ResponseSender sender)> 54 MethodCallCallback; 55 56 // Called when method exporting is done. 57 // |success| indicates whether exporting was successful or not. 58 typedef base::Callback<void (const std::string& interface_name, 59 const std::string& method_name, 60 bool success)> 61 OnExportedCallback; 62 63 // Exports the method specified by |interface_name| and |method_name|, 64 // and blocks until exporting is done. Returns true on success. 65 // 66 // |method_call_callback| will be called in the origin thread, when the 67 // exported method is called. As it's called in the origin thread, 68 // |method_callback| can safely reference objects in the origin thread 69 // (i.e. UI thread in most cases). 70 // 71 // IMPORTANT NOTE: You should export all methods before requesting a 72 // service name by Bus::RequestOwnership/AndBlock(). If you do it in the 73 // wrong order (i.e. request a service name then export methods), there 74 // will be a short time period where your service is unable to respond to 75 // method calls because these methods aren't yet exposed. This race is a 76 // real problem as clients may start calling methods of your service as 77 // soon as you acquire a service name, by watching the name owner change. 78 // 79 // BLOCKING CALL. 80 virtual bool ExportMethodAndBlock(const std::string& interface_name, 81 const std::string& method_name, 82 MethodCallCallback method_call_callback); 83 84 // Requests to export the method specified by |interface_name| and 85 // |method_name|. See Also ExportMethodAndBlock(). 86 // 87 // |on_exported_callback| is called when the method is exported or 88 // failed to be exported, in the origin thread. 89 // 90 // Must be called in the origin thread. 91 virtual void ExportMethod(const std::string& interface_name, 92 const std::string& method_name, 93 MethodCallCallback method_call_callback, 94 OnExportedCallback on_exported_callback); 95 96 // Requests to send the signal from this object. The signal will be sent 97 // synchronously if this method is called from the message loop in the D-Bus 98 // thread and asynchronously otherwise. 99 virtual void SendSignal(Signal* signal); 100 101 // Unregisters the object from the bus. The Bus object will take care of 102 // unregistering so you don't have to do this manually. 103 // 104 // BLOCKING CALL. 105 virtual void Unregister(); 106 107 protected: 108 // This is protected, so we can define sub classes. 109 virtual ~ExportedObject(); 110 111 private: 112 friend class base::RefCountedThreadSafe<ExportedObject>; 113 114 // Helper function for ExportMethod(). 115 void ExportMethodInternal(const std::string& interface_name, 116 const std::string& method_name, 117 MethodCallCallback method_call_callback, 118 OnExportedCallback exported_callback); 119 120 // Called when the object is exported. 121 void OnExported(OnExportedCallback on_exported_callback, 122 const std::string& interface_name, 123 const std::string& method_name, 124 bool success); 125 126 // Helper function for SendSignal(). 127 void SendSignalInternal(base::TimeTicks start_time, 128 DBusMessage* signal_message); 129 130 // Registers this object to the bus. 131 // Returns true on success, or the object is already registered. 132 // 133 // BLOCKING CALL. 134 bool Register(); 135 136 // Handles the incoming request messages and dispatches to the exported 137 // methods. 138 DBusHandlerResult HandleMessage(DBusConnection* connection, 139 DBusMessage* raw_message); 140 141 // Runs the method. Helper function for HandleMessage(). 142 void RunMethod(MethodCallCallback method_call_callback, 143 std::unique_ptr<MethodCall> method_call, 144 base::TimeTicks start_time); 145 146 // Callback invoked by service provider to send a response to a method call. 147 // Can be called immediately from a MethodCallCallback to implement a 148 // synchronous service or called later to implement an asynchronous service. 149 void SendResponse(base::TimeTicks start_time, 150 std::unique_ptr<MethodCall> method_call, 151 std::unique_ptr<Response> response); 152 153 // Called on completion of the method run from SendResponse(). 154 // Takes ownership of |method_call| and |response|. 155 void OnMethodCompleted(std::unique_ptr<MethodCall> method_call, 156 std::unique_ptr<Response> response, 157 base::TimeTicks start_time); 158 159 // Called when the object is unregistered. 160 void OnUnregistered(DBusConnection* connection); 161 162 // Redirects the function call to HandleMessage(). 163 static DBusHandlerResult HandleMessageThunk(DBusConnection* connection, 164 DBusMessage* raw_message, 165 void* user_data); 166 167 // Redirects the function call to OnUnregistered(). 168 static void OnUnregisteredThunk(DBusConnection* connection, 169 void* user_data); 170 171 scoped_refptr<Bus> bus_; 172 ObjectPath object_path_; 173 bool object_is_registered_; 174 175 // The method table where keys are absolute method names (i.e. interface 176 // name + method name), and values are the corresponding callbacks. 177 typedef std::map<std::string, MethodCallCallback> MethodTable; 178 MethodTable method_table_; 179 }; 180 181 } // namespace dbus 182 183 #endif // DBUS_EXPORTED_OBJECT_H_ 184