9dda4f47333978b9ffe1cfa51c71c37c8fccc192
[platform/framework/web/crosswalk-tizen.git] / src / common / dbus_server.cc
1 // Copyright 2015 Samsung Electronics Co, Ltd. 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 #include "common/dbus_server.h"
6
7 #include "common/logger.h"
8
9 namespace wrt {
10
11 namespace {
12
13 static void OnMethodCall(GDBusConnection* connection,
14                          const gchar* /*sender*/,
15                          const gchar* /*object_path*/,
16                          const gchar* interface_name,
17                          const gchar* method_name,
18                          GVariant* parameters,
19                          GDBusMethodInvocation* invocation,
20                          gpointer user_data) {
21   DBusServer* self = reinterpret_cast<DBusServer*>(user_data);
22   if (!self) {
23     LOGGER(ERROR) << "DBusServer is NULL.";
24     return;
25   }
26   auto callback = self->GetMethodCallback(interface_name);
27   if (callback) {
28     callback(connection, method_name, parameters, invocation);
29   }
30 }
31
32 static GVariant* OnGetProperty(GDBusConnection* connection,
33                                const gchar* /*sender*/,
34                                const gchar* /*object_path*/,
35                                const gchar* interface_name,
36                                const gchar* property_name,
37                                GError** /*error*/,
38                                gpointer user_data) {
39   DBusServer* self = reinterpret_cast<DBusServer*>(user_data);
40   if (!self) {
41     LOGGER(ERROR) << "DBusServer is NULL.";
42     return NULL;
43   }
44
45   auto callback =
46       self->GetPropertyGetter(interface_name);
47
48   GVariant* ret = NULL;
49   if (callback) {
50     ret = callback(connection, property_name);
51   }
52
53   return ret;
54 }
55
56 static gboolean OnSetProperty(GDBusConnection* connection,
57                               const gchar* /*sender*/,
58                               const gchar* /*object_path*/,
59                               const gchar* interface_name,
60                               const gchar* property_name,
61                               GVariant* value,
62                               GError** /*error*/,
63                               gpointer user_data) {
64   DBusServer* self = reinterpret_cast<DBusServer*>(user_data);
65   if (!self) {
66     LOGGER(ERROR) << "DBusServer is NULL.";
67     return FALSE;
68   }
69
70   auto callback =
71       self->GetPropertySetter(interface_name);
72
73   gboolean ret = FALSE;
74   if (callback) {
75     if (callback(connection, property_name, value)) {
76       ret = TRUE;
77     }
78   }
79
80   return ret;
81 }
82
83 static const GDBusInterfaceVTable kInterfaceVTable = {
84   OnMethodCall,
85   OnGetProperty,
86   OnSetProperty
87 };
88
89 static void OnClosedConnection(GDBusConnection* connection,
90                                gboolean /*remote_peer_vanished*/,
91                                GError* /*error*/,
92                                gpointer user_data) {
93   g_signal_handlers_disconnect_by_func(connection,
94                                        (gpointer)OnClosedConnection,
95                                        user_data);
96   g_object_unref(connection);
97 }
98
99 static gboolean OnClientRequest(GDBusServer* /*dbus_server*/,
100                                 GDBusConnection* connection,
101                                 gpointer user_data) {
102   GError* err = NULL;
103   DBusServer* self = reinterpret_cast<DBusServer*>(user_data);
104
105   g_signal_connect(connection, "closed",
106                    G_CALLBACK(OnClosedConnection), self);
107
108   if (self) {
109     // Check Peer Credentials
110     DBusServer::PeerCredentialsCallback callback =
111         self->GetPeerCredentialsCallback();
112     if (callback && !callback(
113         g_dbus_connection_get_peer_credentials(connection))) {
114       LOGGER(WARN) << "Invalid peer credentials.";
115       g_dbus_connection_close_sync(connection, NULL, NULL);
116     }
117
118     GDBusNodeInfo* node_info = self->GetIntrospectionNodeInfo();
119     if (!node_info) {
120       LOGGER(ERROR) << "Introspection is not set.";
121       return TRUE;
122     }
123
124     // TODO(wy80.choi): register multiple interfaces
125     g_object_ref(connection);
126     guint reg_id = g_dbus_connection_register_object(
127                           connection,
128                           "/",
129                           node_info->interfaces[0],
130                           &kInterfaceVTable,
131                           self,
132                           NULL,
133                           &err);
134     if (reg_id == 0) {
135       LOGGER(ERROR) << "Failed to register object : " << err->message;
136       g_error_free(err);
137     }
138   }
139   return TRUE;
140 }
141
142 }  // namespace
143
144 DBusServer::DBusServer()
145     : server_(NULL),
146       node_info_(NULL) {
147 }
148
149 DBusServer::~DBusServer() {
150   if (node_info_) {
151     g_dbus_node_info_unref(node_info_);
152   }
153
154   if (server_) {
155     g_object_unref(server_);
156   }
157
158   if (!address_path_.empty()) {
159     unlink(address_path_.c_str());
160   }
161 }
162
163 void DBusServer::Start(const std::string& name) {
164   GError* err = NULL;
165
166   address_path_.clear();
167   address_path_.append(g_get_user_runtime_dir());
168   address_path_.append("/.");
169   address_path_.append(name);
170   // unlink existing bus address
171   unlink(address_path_.c_str());
172
173   std::string address("unix:path=");
174   address.append(address_path_);
175
176   // create new bus socket
177   // TODO(wy80.choi): bus socket (Address) should be removed gracefully
178   // when application is terminated.
179   gchar* guid = g_dbus_generate_guid();
180   server_ = g_dbus_server_new_sync(
181                   address.c_str(), G_DBUS_SERVER_FLAGS_NONE,
182                   guid, NULL, NULL, &err);
183   g_free(guid);
184   if (!server_) {
185     LOGGER(ERROR) << "Failed to create dbus server : " << err->message;
186     g_error_free(err);
187     return;
188   }
189
190   // start server
191   g_signal_connect(server_, "new-connection",
192                    G_CALLBACK(OnClientRequest), this);
193
194   g_dbus_server_start(server_);
195 }
196
197 std::string DBusServer::GetClientAddress() const {
198   return std::string(g_dbus_server_get_client_address(server_));
199 }
200
201 void DBusServer::SetIntrospectionXML(const std::string& xml) {
202   GError* err = NULL;
203   node_info_ = g_dbus_node_info_new_for_xml(xml.c_str(), &err);
204   if (!node_info_) {
205     LOGGER(ERROR) << "Failed to create node info from introspection xml : "
206                   << err->message;
207     g_error_free(err);
208   }
209 }
210
211 void DBusServer::SendSignal(GDBusConnection* connection,
212                             const std::string& iface,
213                             const std::string& signal_name,
214                             GVariant* parameters) {
215   GError* err = NULL;
216   gboolean ret = g_dbus_connection_emit_signal(
217       connection, NULL, "/",
218       iface.c_str(), signal_name.c_str(),
219       parameters, &err);
220   if (!ret) {
221     LOGGER(ERROR) << "Failed to emit signal : '"
222                   << iface << '.' << signal_name << "'";
223     g_error_free(err);
224   }
225 }
226
227 void DBusServer::SetPeerCredentialsCallback(PeerCredentialsCallback func) {
228   peer_credentials_callback_ = func;
229 }
230
231 void DBusServer::SetMethodCallback(
232     const std::string& iface, MethodCallback func) {
233   method_callbacks_[iface] = func;
234 }
235
236 void DBusServer::SetPropertyGetter(
237     const std::string& iface, PropertyGetter func) {
238   property_getters_[iface] = func;
239 }
240
241 void DBusServer::SetPropertySetter(
242     const std::string& iface, PropertySetter func) {
243   property_setters_[iface] = func;
244 }
245
246 DBusServer::PeerCredentialsCallback
247 DBusServer::GetPeerCredentialsCallback() const {
248   return peer_credentials_callback_;
249 }
250
251 DBusServer::MethodCallback
252 DBusServer::GetMethodCallback(const std::string& iface) {
253   return method_callbacks_[iface];
254 }
255
256 DBusServer::PropertySetter
257 DBusServer::GetPropertySetter(const std::string& iface) {
258   return property_setters_[iface];
259 }
260
261 DBusServer::PropertyGetter
262 DBusServer::GetPropertyGetter(const std::string& iface) {
263   return property_getters_[iface];
264 }
265
266 }  // namespace wrt