Remove dependency to security-server.
[platform/core/context/context-common.git] / src / dbus_client.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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 #include <glib.h>
18 #include <gio/gio.h>
19
20 #include <types_internal.h>
21 #include <scope_mutex.h>
22 #include "response_handler.h"
23 #include "dbus_client.h"
24
25 static GDBusConnection *dbus_connection = NULL;
26 static GDBusNodeInfo *dbus_node_info = NULL;
27
28 static const gchar introspection_xml[] =
29         "<node>"
30         "       <interface name='"DBUS_IFACE"'>"
31         "               <method name='"METHOD_RESPOND"'>"
32         "                       <arg type='i' name='"ARG_REQID"' direction='in'/>"
33         "                       <arg type='s' name='"ARG_SUBJECT"' direction='in'/>"
34         "                       <arg type='i' name='"ARG_RESULT_ERR"' direction='in'/>"
35         "                       <arg type='s' name='"ARG_OUTPUT"' direction='in'/>"
36         "               </method>"
37         "       </interface>"
38         "</node>";
39
40 static void handle_response(const gchar *sender, GVariant *param, GDBusMethodInvocation *invocation)
41 {
42         gint req_id = 0;
43         const gchar *subject = NULL;
44         gint error = 0;
45         const gchar *data = NULL;
46
47         g_variant_get(param, "(i&si&s)", &req_id, &subject, &error, &data);
48
49         _I("[Response] ReqId: %d, Subject: %s, Error: %d", req_id, subject, error);
50         _D("Data: %s", data);
51
52         ctx::response_handler::deliver(subject, req_id, error, data);
53
54         g_dbus_method_invocation_return_value(invocation, NULL);
55 }
56
57 static void handle_method_call(GDBusConnection *conn, const gchar *sender,
58                 const gchar *obj_path, const gchar *iface, const gchar *method_name,
59                 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
60 {
61         IF_FAIL_VOID_TAG(STR_EQ(obj_path, DBUS_PATH), _W, "Invalid path: %s", obj_path);
62         IF_FAIL_VOID_TAG(STR_EQ(iface, DBUS_IFACE), _W, "Invalid interface: %s", obj_path);
63
64         if (STR_EQ(method_name, METHOD_RESPOND)) {
65                 handle_response(sender, param, invocation);
66         } else {
67                 _W("Invalid method: %s", method_name);
68         }
69 }
70
71 ctx::dbus_client::dbus_client()
72 {
73 }
74
75 ctx::dbus_client::~dbus_client()
76 {
77         release();
78 }
79
80 bool ctx::dbus_client::init()
81 {
82         static GMutex connection_mutex;
83         ctx::scope_mutex sm(&connection_mutex);
84
85         if (dbus_connection) {
86                 return true;
87         }
88
89         GError *gerr = NULL;
90
91         dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
92         IF_FAIL_RETURN_TAG(dbus_node_info != NULL, false, _E, "Initialization failed");
93
94         gchar *addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr);
95         HANDLE_GERROR(gerr);
96         IF_FAIL_RETURN_TAG(addr != NULL, false, _E, "Getting address failed");
97         _SD("Address: %s", addr);
98
99         dbus_connection = g_dbus_connection_new_for_address_sync(addr,
100                         (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
101                         NULL, NULL, &gerr);
102         g_free(addr);
103         HANDLE_GERROR(gerr);
104         IF_FAIL_RETURN_TAG(dbus_connection != NULL, false, _E, "Connection failed");
105
106         GDBusInterfaceVTable vtable;
107         vtable.method_call = handle_method_call;
108         vtable.get_property = NULL;
109         vtable.set_property = NULL;
110
111         guint reg_id = g_dbus_connection_register_object(dbus_connection, DBUS_PATH,
112                         dbus_node_info->interfaces[0], &vtable, NULL, NULL, &gerr);
113         HANDLE_GERROR(gerr);
114         IF_FAIL_RETURN_TAG(reg_id>0, false, _E, "Object registration failed");
115
116         _I("Dbus connection established: %s", g_dbus_connection_get_unique_name(dbus_connection));
117         return true;
118 }
119
120 void ctx::dbus_client::release()
121 {
122         if (dbus_connection) {
123                 g_dbus_connection_flush_sync(dbus_connection, NULL, NULL);
124                 g_dbus_connection_close_sync(dbus_connection, NULL, NULL);
125                 g_object_unref(dbus_connection);
126                 dbus_connection = NULL;
127         }
128
129         if (dbus_node_info) {
130                 g_dbus_node_info_unref(dbus_node_info);
131                 dbus_node_info = NULL;
132         }
133 }
134
135 int ctx::dbus_client::request(
136                 int type, int req_id, const char* subject, const char* input,
137                 std::string* req_result, std::string* data_read)
138 {
139         _I("Requesting: %d, %d, %s, %s", type, req_id, subject, input);
140
141         if (subject == NULL) {
142                 subject = EMPTY_STRING;
143         }
144
145         if (input == NULL) {
146                 input = EMPTY_JSON_OBJECT;
147         }
148
149         /* FIXME: the second param is the security cookie, which is deprected in 3.0.
150          * We need to completely REMOVE this parameter from the dbus protocol. */
151         GVariant *param = g_variant_new("(isiss)", type, "", req_id, subject, input);
152         IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
153
154         GError *err = NULL;
155         GVariant *response = g_dbus_connection_call_sync(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE,
156                         METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err);
157         HANDLE_GERROR(err);
158         IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed");
159
160         gint _error = ERR_OPERATION_FAILED;
161         const gchar *_req_result = NULL;
162         const gchar *_data_read = NULL;
163
164         g_variant_get(response, "(i&s&s)", &_error, &_req_result, &_data_read);
165         if (req_result) {
166                 *req_result = _req_result;
167         }
168         if (data_read) {
169                 *data_read = _data_read;
170         }
171
172         g_variant_unref(response);
173
174         return _error;
175 }
176
177 int ctx::dbus_client::request_with_no_reply(
178                 int type, int req_id, const char* subject, const char* input)
179 {
180         _I("Requesting: %d, %d, %s, %s", type, req_id, subject, input);
181
182         if (subject == NULL) {
183                 subject = EMPTY_STRING;
184         }
185
186         if (input == NULL) {
187                 input = EMPTY_JSON_OBJECT;
188         }
189
190         /* FIXME: the second param is the security cookie, which is deprected in 3.0.
191          * We need to completely REMOVE this parameter from the dbus protocol. */
192         GVariant *param = g_variant_new("(isiss)", type, "", req_id, subject, input);
193         IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
194
195         GError *err = NULL;
196         g_dbus_connection_call(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE,
197                         METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err);
198
199         if (err) {
200                 HANDLE_GERROR(err);
201                 return ERR_OPERATION_FAILED;
202         }
203
204         return ERR_NONE;
205 }