change tlm dbus path to combination of seat id and uid
[profile/tv/apps/native/homescreen.git] / src / Bus.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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 <gio/gio.h>
18 #include <stdlib.h>
19
20 #include "Bus.h"
21 #include <AppCommon.h>
22
23 #define ADDRESS_BUF_MAX 128
24
25 /* FIXME: fix seat id, it should be changed */
26 #define TLM_SEAT_ID "seat0"
27 #define TLM_DBUS_SOCKET_PATH "/var/run/tlm/"
28
29 struct SBus {
30         CBus::SCallback cb;
31 };
32
33 bool CBus::t_GetContent(GVariantIter *it, SContent *content)
34 {
35         ASSERT(content);
36
37         guchar type;
38         const gchar *thumbnail;
39         gboolean r;
40
41         r = g_variant_iter_next(it, "(ys)", &type, &thumbnail);
42         if (!r)
43                 return false;
44
45         content->type = (EContentType)type;
46         content->thumbnail = thumbnail;
47
48         return true;
49 }
50
51
52 bool CBus::t_GetContentArray(SContent contents[], int arraymax, int *cnt)
53 {
54         ASSERT(contents);
55
56         GVariant *val;
57         GVariantIter _it;
58         int i = 0;
59
60         val = g_variant_iter_next_value(Iter());
61         if (val) {
62                 if (g_variant_is_of_type(val, G_VARIANT_TYPE_ARRAY)) {
63
64                         g_variant_iter_init(&_it, val);
65
66                         for (i = 0; i < arraymax; i++) {
67                                 if (t_GetContent(&_it, &contents[i]) == false)
68                                         break;
69                         }
70
71                         if (cnt)
72                                 *cnt = i;
73                 }
74                 else {
75                         _ERR("Not array");
76                 }
77                 g_variant_unref(val);
78         }
79         return i ? true : false;
80 }
81
82
83 void CBus::t_ReleaseContentArray(SContent contents[], int arraymax)
84 {
85         int i;
86
87         for (i = 0; i < arraymax; i++)
88                 g_free((gpointer)contents[i].thumbnail);
89 }
90
91 bool CBus::t_OnEvent(const char *method, GVariant *param)
92 {
93         bool ret = false;
94
95         if (strcmp(BUS_METHOD_ADD_ALBUM, method) == 0) {
96                 ret = t_EventAddAlbum(param);
97         }
98         else if (strcmp(BUS_METHOD_ADD_LABEL, method) == 0) {
99                 ret = t_EventAddLabel(param);
100         }
101         else if (strcmp(BUS_METHOD_ADD_PIN, method) == 0) {
102                 ret = t_EventAddPin(param);
103         }
104         else if (strcmp(BUS_METHOD_DEL_ALL, method) == 0) {
105                 ret = t_EventDelAllContent(param);
106         }
107         else if (strcmp(BUS_METHOD_ADD_CONTENTS, method) == 0) {
108                 ret = t_EventAddContents(param);
109         }
110
111         return ret;
112 }
113
114 bool CBus::t_EventAddLabel(GVariant *param)
115 {
116         ASSERT(param);
117
118         SLabel data;
119
120         memset(&data, 0, sizeof(data));
121         SetParcel(param);
122
123         data.svcid = String();
124         data.title = String();
125         if (!data.svcid || !data.title) {
126                 _ERR("svcid: 0x%x, title: 0x%x / get failed", data.svcid, data.title);
127                 return false;
128         }
129
130         return OnAddLabel(&data);
131 }
132
133 bool CBus::t_EventAddAlbum(GVariant *param)
134 {
135         ASSERT(param);
136
137         bool ret;
138         SAlbum  cAlbum;
139         SAction cAction;
140
141         memset(&cAlbum, 0x00, sizeof(cAlbum));
142         memset(&cAction, 0x00, sizeof(cAction));
143         SetParcel(param);
144
145         cAlbum.svcid = String();
146         cAlbum.title = String();
147         if (!cAlbum.svcid || !cAlbum.title) {
148                 _ERR("svcid: 0x%x, title: 0x%x / id get failed", cAlbum.svcid, cAlbum.title);
149                 return false;
150         }
151
152         ret = t_GetContentArray(cAlbum.contents,
153                         BUS_DATA_ALBUM_CONTENT_MAX, &cAlbum.content_cnt);
154         if (ret == false) {
155                 _ERR("contents get failed");
156                 return false;
157         }
158
159         cAction.action = (EActionOp)Byte();
160         cAction.actor = String();
161         cAction.args  = String();
162
163         ret = OnAddAlbum(&cAlbum, &cAction);
164         t_ReleaseContentArray(cAlbum.contents, BUS_DATA_ALBUM_CONTENT_MAX);
165
166         return ret;
167 }
168
169 bool CBus::t_EventAddContents(GVariant *param)
170 {
171         ASSERT(param);
172
173         GVariantIter iter,_it;
174         GVariant *val;
175         const gchar *svcid, *title, *subtitle, *descr, *detail, *icon, *thumb, *actor, *args;
176         guchar type, action;
177         Eina_List *list;
178         SContent *cContent;
179
180         g_variant_iter_init(&iter, param);
181         val = g_variant_iter_next_value(&iter);
182         g_variant_iter_init(&_it, val);
183
184         list = NULL;
185
186         while (g_variant_iter_next(&_it, "(sssssyssyss)", &svcid, &title, &subtitle,
187                                 &descr, &detail, &type, &thumb, &icon, &action, &actor, &args)) {
188                 if (!svcid) {
189                         _ERR("failed to get service id");
190                         continue;
191                 }
192
193                 cContent = (SContent *)calloc(1, sizeof(*cContent));
194                 if (!cContent) {
195                         _ERR("calloc failed");
196                         continue;
197                 }
198
199                 cContent->svcid = svcid;
200                 cContent->title = title ? title : "";
201                 cContent->subtitle = subtitle ? subtitle : "";
202                 cContent->description = descr ? descr : "";
203                 cContent->detail = detail ? detail : "";
204                 cContent->type = (EContentType)type;
205                 cContent->thumbnail = thumb ? thumb : "";
206                 cContent->icon = icon ? icon : "";
207                 cContent->action = (EActionOp)action;
208                 cContent->actor = actor ? actor : "";
209                 cContent->args = args ? args : "";
210
211                 list = eina_list_append(list, cContent);
212         }
213
214         g_variant_unref(val);
215         g_variant_unref(param);
216
217         return OnAddContents(list);
218 }
219
220 bool CBus::t_EventAddPin(GVariant *param)
221 {
222         ASSERT(param);
223
224         SPin    cPin;
225         SAction cAction;
226         memset(&cPin, 0x00, sizeof(cPin));
227         SetParcel(param);
228
229         cPin.svcid = String();
230         cPin.title = String();
231         if (!cPin.svcid || !cPin.title) {
232                 _ERR("svcid: 0x%x, title: 0x%x / id get failed", cPin.svcid, cPin.title);
233                 return false;
234         }
235
236         cPin.type      = (EPinType)Byte();
237         cPin.icon      = String();
238         cPin.pinid     = String();
239         cAction.action = (EActionOp)Byte();
240         cAction.actor  = String();
241         cAction.args   = String();
242
243         return OnAddPin(&cPin, &cAction);
244 }
245
246 bool CBus::t_EventDelAllContent(GVariant *param)
247 {
248         ASSERT(param);
249
250         const gchar *svcid;
251         bool reload;
252
253         SetParcel(param);
254         svcid = String();
255         if (!svcid) {
256                 _ERR("Service id get failed");
257                 return false;
258         }
259
260         reload = Boolean();
261
262         return OnDelAll(svcid, reload);
263 }
264
265 bool CBus::Create(const SCallback *cb)
266 {
267         ASSERT(!FlagCreate());
268
269         m = new SBus;
270         if (!m) {
271                 _ERR("calloc failed");
272                 return false;
273         }
274
275         if (!CBaseBus::Create(cb, BUS_NAME, BUS_OBJECT_PATH, BUS_INTERFACE, BUS_TYPE)) {
276                 delete m;
277                 m = NULL;
278                 return false;
279         }
280
281         m->cb = *cb;
282
283         return true;
284 }
285
286 void CBus::Destroy(void)
287 {
288         ASSERT(FlagCreate());
289
290         CBaseBus::Destroy();
291         delete m;
292         m = NULL;
293 }
294
295 bool CBus::OnAddLabel(SLabel *opdata)
296 {
297         bool ret = false;
298
299         if (m->cb.cbAddLabel)
300                 ret = m->cb.cbAddLabel(opdata, m->cb.cookie);
301
302         return ret;
303 }
304
305 bool CBus::OnAddAlbum(SAlbum *opdata, SAction *act)
306 {
307         bool ret = false;
308
309         if (m->cb.cbAddAlbum)
310                 ret = m->cb.cbAddAlbum(opdata, act, m->cb.cookie);
311
312         return ret;
313 }
314
315 bool CBus::OnAddContents(Eina_List *list)
316 {
317         bool ret = false;
318
319         if (m->cb.cbAddContents)
320                 ret = m->cb.cbAddContents(list, m->cb.cookie);
321
322         return ret;
323 }
324
325 bool CBus::OnAddPin(SPin *opdata, SAction *act)
326 {
327         bool ret = false;
328
329         if (m->cb.cbAddPin)
330                 ret = m->cb.cbAddPin(opdata, act, m->cb.cookie);
331
332         return ret;
333 }
334
335 bool CBus::OnDelAll(const char *svcid, bool reload)
336 {
337         bool ret = false;
338
339         if (m->cb.cbDelAll)
340                 ret = m->cb.cbDelAll(svcid, reload, m->cb.cookie);
341
342         return ret;
343 }
344
345 /**
346  * bus send changed user, client program start
347  */
348 static GDBusConnection *_get_bus_connection(GError **error)
349 {
350         gchar address[ADDRESS_BUF_MAX];
351
352         g_snprintf(address, ADDRESS_BUF_MAX - 1, "unix:path=%s%s-%u",
353                                 TLM_DBUS_SOCKET_PATH, TLM_SEAT_ID, getuid());
354
355         return g_dbus_connection_new_for_address_sync(address,
356                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL,
357                         NULL, error);
358 }
359
360 static GVariant *_build_env_param(const char *username, const char *password)
361 {
362         GVariantBuilder *builder;
363         GVariant *param, *env;
364
365         if (!username || !password) {
366                 _ERR("Invalid arguement");
367                 return NULL;
368         }
369
370         builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
371         if (!builder) {
372                 _ERR("builder new failed");
373                 return NULL;
374         }
375         g_variant_builder_add(builder, "{ss}", "", "");
376         env = g_variant_builder_end(builder);
377         g_variant_builder_unref(builder);
378
379         param = g_variant_new("(sss@a{ss})",
380                         TLM_SEAT_ID, username, password, env);
381
382         return param;
383 }
384
385 int bus_change_user(const char *username, const char *password)
386 {
387         GDBusConnection *conn;
388         GError *error;
389         GVariant *param;
390         GDBusMessage *msg, *res;
391         guint32 serial;
392
393         if (!username || !password) {
394                 _ERR("Invalid argument");
395                 return -1;
396         }
397
398         error = NULL;
399         conn = _get_bus_connection(&error);
400         if (!conn) {
401                 _ERR("failed to get connection, %s",
402                                 error ? error->message : "");
403                 g_error_free(error);
404                 return -1;
405         }
406
407         param = _build_env_param(username, password);
408         if (!param) {
409                 _ERR("failed to build env param");
410                 g_object_unref(conn);
411                 return -1;
412         }
413
414         msg = g_dbus_message_new_method_call("org.O1.Tlm.Login",
415                         "/org/O1/Tlm/Login", "org.O1.Tlm.Login",
416                         "switchUser");
417         g_dbus_message_set_body(msg, param);
418
419         error = NULL;
420         res = g_dbus_connection_send_message_with_reply_sync(conn, msg,
421                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
422                         1000, &serial, NULL, &error);
423         if (!res) {
424                 _ERR("failed to switch user, %s", error ? error->message : "");
425                 g_object_unref(msg);
426                 g_object_unref(conn);
427                 g_error_free(error);
428                 return -1;
429         }
430
431         _DBG("User changed successfully: %u", serial);
432
433         g_object_unref(res);
434         g_object_unref(msg);
435         g_object_unref(conn);
436
437         return 0;
438 }