bug fix to pass action and actor arguments when created as a dbar item
[profile/tv/apps/native/homescreen.git] / src / engine.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 <stdio.h>
18 #include <stdlib.h>
19 #include <limits.h>
20 #include <Eina.h>
21 #include <json-glib/json-glib.h>
22 #include <aul.h>
23 #include <ctype.h>
24 #include <sys/time.h>
25 #include <app-content.h>
26 #include <gum/gum-user.h>
27 #include <gum/gum-user-service.h>
28 #include <gum/common/gum-user-types.h>
29 #include <Elementary.h>
30 #include <cynara-client.h>
31 #include <pwd.h>
32
33 #include "common.h"
34 #include "Bus.h"
35 #include "engine.h"
36 #include "ClientBus.h"
37 #include "defs.h"
38 #include "dbg.h"
39
40 #define SECTION_USER "user"
41 #define SECTION_UBAR_ITEMS "ubar.items"
42 #define SECTION_ITEMS "items"
43
44 #define ATTR_NAME "name"
45 #define ATTR_ICON "icon"
46 #define ATTR_ICON_FOCUS "icon_focus"
47 #define ATTR_BUS_NAME "bus_name"
48 #define ATTR_OBJECT_PATH "object_path"
49 #define ATTR_APP "app"
50 #define ATTR_COLOR "color"
51 #define ATTR_RED "red"
52 #define ATTR_GREEN "green"
53 #define ATTR_BLUE "blue"
54 #define ATTR_CONTENTS "contents"
55 #define ATTR_NOCTNT_TITLE "noctnt_title"
56 #define ATTR_NOCTNT_DESC "noctnt_desc"
57 #define ATTR_CONTENT_COLUMN "content_column"
58 #define ATTR_IN "in"
59
60 #define SIZE_32 32
61 #define SIZE_4 4
62 #define MULTIPLIER 1024
63
64 struct SEngine {
65         struct {
66                 char *name;
67                 char *thumb_bg;
68                 char *thumb;
69         }   user;
70
71         CBus *bus;
72         Eina_List *client_buslist;
73
74         Eina_List *hbar_its;
75         Eina_List *ubar_its;
76         Eina_List *pin_its;
77         Eina_Bool is_full;
78
79         CAppContentHistory *pAppContentHistory;
80         CAppContentFavorite *pAppContentFavorite;
81         CAppContentPin *pAppContentPin;
82
83         void (*update_cb)(void *data, bool focus);
84         void *update_cb_data;
85
86         SEngine() {
87                 memset(this, 0, sizeof(SEngine));
88         };
89 };
90
91 static int _is_member_exist(JsonReader *reader, const char *member_name)
92 {
93         gchar **members;
94         int i, cnt;
95         int r;
96
97         cnt = json_reader_count_members(reader);
98         if (cnt == -1) {
99                 _ERR("No member");
100                 return 0;
101         }
102         members = json_reader_list_members(reader);
103         if (!members) {
104                 _ERR("No member");
105                 return 0;
106         }
107
108         r = 0;
109         for (i = 0; i < cnt; i++) {
110                 if (!strcmp(member_name, members[i])) {
111                         r = 1;
112                         break;
113                 }
114         }
115
116         g_strfreev(members);
117
118         return r;
119 }
120
121 static inline const char *_read_attr(JsonReader *reader, const char *attr)
122 {
123         const char *val;
124
125         if (!reader || !attr)
126                 return NULL;
127
128         if (!_is_member_exist(reader, attr)) {
129                 _ERR("There is no %s attribute", attr);
130                 return NULL;
131         }
132
133         json_reader_read_member(reader, attr);
134         val = json_reader_get_string_value(reader);
135         json_reader_end_member(reader);
136
137         return val;
138 }
139
140 static inline gint64 _read_attr_int(JsonReader *reader, const char *attr)
141 {
142         gint64 val;
143
144         if (!reader || !attr)
145                 return 0;
146
147         if (!_is_member_exist(reader, attr)) {
148                 _ERR("There is no %s attribute", attr);
149                 return 0;
150         }
151
152         json_reader_read_member(reader, attr);
153         val = json_reader_get_int_value(reader);
154         json_reader_end_member(reader);
155
156         return val;
157 }
158
159 static JsonReader *_get_reader(JsonParser *parser)
160 {
161         ASSERT(parser);
162
163         return json_reader_new(json_parser_get_root(parser));
164 }
165
166
167 void CEngine::_unload_config_user(void)
168 {
169         free(m->user.name);
170         free(m->user.thumb_bg);
171         free(m->user.thumb);
172 }
173
174 bool _read_color(JsonReader *reader, gint64 *r, gint64 *g, gint64 *b)
175 {
176         ASSERT(reader);
177         ASSERT(r && g && b);
178
179         if (!_is_member_exist(reader, ATTR_COLOR)) {
180                 _ERR("There is no "ATTR_COLOR" attribute");
181
182                 *r = 69;
183                 *g = 143;
184                 *b = 255;
185
186                 return false;
187         }
188         json_reader_read_member(reader, ATTR_COLOR);
189         *r = _read_attr_int(reader, ATTR_RED);
190         *g = _read_attr_int(reader, ATTR_GREEN);
191         *b = _read_attr_int(reader, ATTR_BLUE);
192         json_reader_end_member(reader);
193
194         return true;
195 }
196
197 static void _string_to_uppercase(char *str)
198 {
199         while (*str != '\0')
200                 *(str++) = toupper(*str);
201 }
202
203 static char *_get_unique_id(const char *object_path, char *uuid)
204 {
205         struct timezone timezone;
206         struct timeval timeval;
207         int len;
208         int i;
209         union {
210                 unsigned int t;
211                 unsigned char ct[SIZE_4];
212         } u1, u2;
213
214         if (!object_path)
215                 return NULL;
216
217         gettimeofday(&timeval, &timezone);
218
219         u1.t = (unsigned int)timeval.tv_usec;
220
221         len = strlen(object_path);
222         u2.t = 0;
223         for (i = 0; i < len; i++)
224                 u2.t = u2.t + MULTIPLIER * (unsigned int)object_path[i];
225
226         snprintf(uuid, SIZE_32, "%02x%02x.%02x%02x.%02x%02x.%02x%02x",
227                         (unsigned char)u2.ct[3], (unsigned char)u2.ct[2],
228                         (unsigned char)u2.ct[1], (unsigned char)u2.ct[0],
229                         (unsigned char)u1.ct[3], (unsigned char)u1.ct[2],
230                         (unsigned char)u1.ct[1], (unsigned char)u1.ct[0]);
231
232         _string_to_uppercase(uuid);
233
234         return strdup(uuid);
235 }
236
237 CEngineBarItem *CEngineBarItem::Alloc(JsonReader *reader, int idx)
238 {
239         CEngineBarItem *it;
240         const char *name, *icon, *icon_focus, *app, *in;
241         const char *object_path, *bus_name;
242         const char *noctnt_title, *noctnt_desc;
243         gint64 r, g, b;
244         gint64 column;
245
246         _CREATE_BEGIN{
247                 _CHECK(json_reader_read_element(reader, idx));
248                 _CHECK(it = new CEngineBarItem);
249                 _CHECK(name = _read_attr(reader, ATTR_NAME));
250                 _CHECK(icon = _read_attr(reader, ATTR_ICON));
251                 _CHECK(icon_focus = _read_attr(reader, ATTR_ICON_FOCUS));
252                 _CHECK(bus_name = _read_attr(reader, ATTR_BUS_NAME));
253                 _CHECK(object_path = _read_attr(reader, ATTR_OBJECT_PATH));
254                 _CHECK(in = _read_attr(reader, ATTR_IN));
255
256                 _CHECK_FAIL{}
257                 _CHECK_FAIL{}
258                 _CHECK_FAIL{}
259                 _CHECK_FAIL{}
260                 _CHECK_FAIL{}
261                 _CHECK_FAIL{}
262                 _CHECK_FAIL{ delete it; }
263                 _CHECK_FAIL{ json_reader_end_element(reader); }
264         } _CREATE_END_AND_CATCH{ return NULL; }
265
266         app          = _read_attr(reader, ATTR_APP);
267         noctnt_title = _read_attr(reader, ATTR_NOCTNT_TITLE);
268         noctnt_desc  = _read_attr(reader, ATTR_NOCTNT_DESC);
269         column       = _read_attr_int(reader, ATTR_CONTENT_COLUMN);
270         if (!column)
271                 column = 1;
272
273         _read_color(reader, &r, &g, &b);
274         json_reader_end_element(reader);
275
276         char uuid[SIZE_32];
277         it->SetStr(VSTR_NAME, name); // it->SetName(name);
278         it->SetStr(VSTR_ICON, icon); // it->SetIcon(icon);
279         it->SetStr(VSTR_ICON_FOCUS, icon_focus);// it->SetIconFocus(icon_focus);
280         it->SetStr(VSTR_OBJECT_PATH, object_path);// it->SetObjectPath(object_path);
281         it->SetStr(VSTR_BUS_NAME, bus_name);// it->SetBusName(bus_name);
282         it->SetStr(VSTR_SVC_ID, _get_unique_id(object_path, uuid));// it->SetSvcId(id);
283         it->SetStr(VSTR_IN, in);// it->SetIn(in);
284         it->SetStr(VSTR_APP, app);// it->SetApp(app);
285         it->SetStr(VSTR_NOCTNT_TITLE, noctnt_title);// it->SetNoctntTitle(noctnt_title);
286         it->SetStr(VSTR_NOCTNT_DESC, noctnt_desc);// it->SetNoctntDesc(noctnt_desc);
287         it->SetColor(r, g, b);
288         it->SetInt(VINT_COLUMN, column);
289
290         return it;
291 }
292
293 bool CEngine::_load_bar_items(JsonReader *reader)
294 {
295         ASSERT(reader);
296
297         CEngineBarItem *it;
298         int i, cnt;
299         CClientBus *cbus;
300
301         if (!_is_member_exist(reader, SECTION_ITEMS)) {
302                 _ERR("There is no "SECTION_ITEMS" field");
303                 return false;
304         }
305         json_reader_read_member(reader, SECTION_ITEMS);
306         if (!json_reader_is_array(reader)) {
307                 _ERR(SECTION_ITEMS" is not array");
308                 goto err;
309         }
310
311         cnt = json_reader_count_elements(reader);
312         for (i = 0; i < cnt; i++) {
313                 it = CEngineBarItem::Alloc(reader, i);
314                 if (!it)
315                         continue;
316
317                 it->SetEngine(this);
318                 m->hbar_its = eina_list_append(m->hbar_its, it);
319
320                 /* send unique id to each content provider */
321                 cbus = new CClientBus;
322                 if (!cbus) {
323                         _ERR(" Unable to allocate memory for client bus");
324                         continue;
325                 }
326                 cbus->Create(
327                         it->Str(CEngineBarItem::VSTR_BUS_NAME),
328                         it->Str(CEngineBarItem::VSTR_OBJECT_PATH),
329                         it->Str(CEngineBarItem::VSTR_SVC_ID)
330                         );
331                 if (!cbus->FlagCreate()) {
332                         _ERR(" Unable to init client bus ");
333                         delete cbus;
334                         continue;
335                 }
336                 cbus->SendSvcid();
337                 m->client_buslist = eina_list_append(m->client_buslist,
338                                 cbus);
339         }
340         json_reader_end_member(reader);
341
342         return true;
343
344 err:
345         json_reader_end_member(reader);
346
347         return false;
348 }
349
350 void CEngine::_unload_bar_items(void)
351 {
352         CEngineBarItem *it;
353         void *obj;
354
355         if (!m->hbar_its) {
356                 _ERR("Invalid argument");
357                 return;
358         }
359
360         EINA_LIST_FREE(m->hbar_its, obj) {
361                 it = (CEngineBarItem *)obj;
362                 delete it;
363         }
364         m->hbar_its = NULL;
365 }
366
367 void CEngine::_unload_ubar_items(void)
368 {
369         CEngineUBarItem *it;
370         void *obj;
371
372         if (!m->ubar_its) {
373                 _ERR("Invalid argument");
374                 return;
375         }
376
377         EINA_LIST_FREE(m->ubar_its, obj) {
378                 it = (CEngineUBarItem *)obj;
379                 delete it;
380         }
381         m->ubar_its = NULL;
382 }
383
384 static JsonParser *_get_parser(const char *config)
385 {
386         ASSERT(config);
387
388         JsonParser *parser;
389         gboolean r;
390
391         parser = json_parser_new();
392         if (!parser) {
393                 _ERR("json parser new failed");
394                 return NULL;
395         }
396
397         r = json_parser_load_from_file(parser, config, NULL);
398         if (!r) {
399                 _ERR("parser load from file failed");
400                 g_object_unref(parser);
401                 return NULL;
402         }
403
404         return parser;
405 }
406
407 bool CEngine::m_LoadItemConfig(void)
408 {
409         JsonParser *parser;
410         JsonReader *reader;
411
412         _CREATE_BEGIN{
413                 _CHECK(parser = _get_parser(DEF_CONFIG));
414                 _CHECK(reader = _get_reader(parser));
415                 _CHECK(_load_bar_items(reader));
416
417                 _CHECK_FAIL{ /* _load_bar_items(reader) */ }
418                 _CHECK_FAIL{ g_object_unref(reader); }
419                 _CHECK_FAIL{ g_object_unref(parser); }
420         } _CREATE_END_AND_CATCH{ return false; }
421
422         g_object_unref(reader);
423         g_object_unref(parser);
424
425         return true;
426 }
427
428 CEngineUBarItem *CEngineUBarItem::Alloc(CEngine *eng, const char *name, const char *icon)
429 {
430         ASSERT(name);
431
432         CEngineUBarItem *it;
433
434         it = new CEngineUBarItem(eng);
435         if (!it) {
436                 _ERR("calloc failed");
437                 return NULL;
438         }
439
440         if (!icon || strlen(icon) == 0)
441                 icon = DEF_USER_THUMB;
442
443         it->SetStr(VSTR_NAME, name);
444         it->SetStr(VSTR_THUMB, icon);
445
446         return it;
447 }
448
449 static gchar **_append_string(gchar **src_strv, const gchar *string)
450 {
451         gchar **dest_strv;
452         gint ind;
453         gint len;
454
455         if (src_strv)
456                 len = g_strv_length(src_strv);
457
458         len = 0;
459         ind = 0;
460         dest_strv = NULL;
461
462         dest_strv = (gchar **)g_malloc0 (sizeof (gchar *) * (len + 2));
463         if (src_strv) {
464                 while (src_strv[ind]) {
465                         dest_strv[ind] = g_strdup (src_strv[ind]);
466                         ind++;
467                 }
468         }
469
470         dest_strv[ind++] = g_strdup (string);
471         dest_strv[ind] = NULL;
472
473         return dest_strv;
474 }
475
476 int CEngine::_load_login_user(uid_t uid)
477 {
478         GumUser *user;
479         const char *icon, *name;
480         struct passwd *passwd;
481
482         user = gum_user_get_sync(uid, FALSE);
483         if (!user) {
484                 _ERR("failed to get login user");
485                 passwd = getpwuid(uid);
486                 m->user.name = strdup(passwd->pw_name ? passwd->pw_name : DEF_USER_NAME);
487                 m->user.thumb = strdup(DEF_USER_THUMB);
488                 return -1;
489         }
490
491         icon = NULL;
492         name = NULL;
493         g_object_get(G_OBJECT(user), GUM_ATTR_NAME, &name,
494                         GUM_ATTR_ICON, &icon, NULL);
495
496         if (!icon || strlen(icon) == 0)
497                 icon = DEF_USER_THUMB;
498
499         m->user.name = strdup(name);
500         m->user.thumb = strdup(icon);
501
502         g_object_unref(user);
503
504         return 0;
505 }
506
507 bool CEngine::m_LoadUser(void)
508 {
509         GumUserList *list;
510         GumUser *user;
511         GumUserService *service;
512         gchar **strv;
513         int i, r;
514         uid_t user_uid, uid;
515         CEngineUBarItem *it;
516         const char *icon, *name;
517
518         user_uid = getuid();
519
520         r = _load_login_user(user_uid);
521         if (r < 0) {
522                 _ERR("failed to load login user");
523                 return true;
524         }
525
526         if (GetPrivilege()) {
527                 it = CEngineUBarItem::Alloc(this, DEF_ADD_NAME, DEF_ADD_THUMB);
528                 if (it) {
529                         m->ubar_its = eina_list_append(m->ubar_its, it);
530                 }
531         }
532
533         service = gum_user_service_create_sync(FALSE);
534         if (!service) {
535                 _ERR("failed to create service");
536                 return false;
537         }
538
539         strv = _append_string(NULL, "normal");
540         list = gum_user_service_get_user_list_sync(service,
541                         (const gchar *const *)strv);
542         g_strfreev(strv);
543
544         if (!list) {
545                 g_object_unref(service);
546                 _ERR("failed to get user list");
547                 return false;
548         }
549
550         for (i = 0; i < (int)g_list_length(list); i++) {
551                 user = (GumUser *)g_list_nth_data(list, i);
552                 if (!user)
553                         continue;
554
555                 g_object_get(G_OBJECT(user), GUM_ATTR_UID, &uid,
556                                 GUM_ATTR_NAME, &name,
557                                 GUM_ATTR_ICON, &icon, NULL);
558                 if (uid == user_uid)
559                         continue;
560
561                 it = CEngineUBarItem::Alloc(this, name, icon);
562                 if (it)
563                         m->ubar_its = eina_list_append(m->ubar_its, it);
564         }
565
566         gum_user_service_list_free(list);
567         g_object_unref(service);
568
569         return true;
570 }
571
572 void CEngine::m_UnloadConfig(void)
573 {
574         _unload_config_user();
575         _unload_bar_items();
576         _unload_ubar_items();
577 }
578
579 void CEngine::sm_CbBusReady(CBaseBus *bus, void *data)
580 {
581         bus->SendSignal(BUS_SIGNAL_REFRESH);
582 }
583
584 void CEngine::sm_CbBusEnd(CBaseBus *bus, void *data)
585 {
586 }
587
588 static int _add_dbar_item(CEngineBarItem *hit,
589                 CEngineDBarItem::EStyle style,
590                 const char *name, CBus::SContent bus_ctnt[],
591                 int ctnt_cnt, CBus::EActionOp action,
592                 const char *actor, const char *args)
593 {
594         CEngineDBarItem *dit;
595         CEngineDBarItemContent *ctnt;
596         int i;
597
598         if (!hit) {
599                 _ERR("Invalid argument");
600                 return -1;
601         }
602
603         dit = new CEngineDBarItem(hit);
604         if (!dit) {
605                 _ERR("calloc failed");
606                 return -1;
607         }
608
609         dit->SetStr(CEngineDBarItem::VSTR_NAME, name ? name : "No Information");
610
611         if (ctnt_cnt > BUS_DATA_ALBUM_CONTENT_MAX)
612                 ctnt_cnt = BUS_DATA_ALBUM_CONTENT_MAX;
613
614         if (bus_ctnt) {
615                 for (i = 0; i < ctnt_cnt; i++) {
616                         ctnt = CEngineDBarItemContent::Alloc(&bus_ctnt[i]);
617                         if (!ctnt)
618                                 break;
619                         dit->AddContent(ctnt);
620                 }
621         }
622
623         hit->SetCtntId(hit->CtntId() + 1);
624         dit->SetInt(CEngineDBarItem::VINT_CONTENT_ID, hit->CtntId()); //dit->SetCtntId(hit->CtntId());//dit->ctnt_id = hit->ctnt_id++;
625         dit->SetInt(CEngineDBarItem::VINT_STYLE, style); // SetStyle(style);// dit->style = style;
626         dit->SetInt(CEngineDBarItem::VINT_ACTION, action); // dit->SetAction(action);// dit->action = action;
627         dit->SetStr(CEngineDBarItem::VSTR_ACTOR, actor);   // dit->SetActor(actor);// if (actor)dit->actor = strdup(actor);
628         dit->SetStr(CEngineDBarItem::VSTR_ARGS, args);   // dit->SetArgs(args);// if (args) dit->args = strdup(args);
629
630         hit->AddItem(dit);//hit->dbar_its = eina_list_append(hit->dbar_its, dit);
631         hit->InvokeUpdateCallback();
632
633         return dit->Int(CEngineDBarItem::VINT_CONTENT_ID);// dit->CtntId();
634 }
635
636 static int _del_dbar_item(CEngineBarItem *hit, int ctnt_id)
637 {
638         if (!hit)
639                 return -1;
640
641         return hit->RemoveDBar(ctnt_id) ? 0 : -1;
642 }
643
644 static int _del_dbar_item_all(CEngineBarItem *hit)
645 {
646         if (!hit)
647                 return -1;
648
649         hit->RemoveAllDBar();
650         hit->InvokeUpdateCallback();
651
652         return 0;
653 }
654
655 bool CEngine::sm_CbAddLabel(CBus::SLabel *lbl, void *data)
656 {
657         CEngine *root = (CEngine*)data;
658         bool ret = false;
659         if (root)
660                 ret = root->m_OnAddLabel(lbl);
661         return ret;
662 }
663
664 bool CEngine::m_OnAddLabel(CBus::SLabel *lbl)
665 {
666         CEngineBarItem *hit;
667         Eina_List *l;
668         void *obj;
669
670         if (!lbl) {
671                 _ERR("Invalid argument");
672                 return false;
673         }
674
675         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
676                 hit = (CEngineBarItem *)obj;
677                 if (strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), lbl->svcid))
678                         continue;
679
680                 return _add_dbar_item(hit, CEngineDBarItem::STYLE_LABEL,
681                                 lbl->title, NULL, 0,
682                                 CBus::ACTION_OP_LAUNCH_NONE,
683                                 NULL, NULL);
684         }
685
686         return false;
687 }
688
689 bool CEngine::sm_CbAddAlbum(CBus::SAlbum *album, CBus::SAction *act, void *data)
690 {
691         CEngine *root = (CEngine*)data;
692         bool ret = false;
693
694         if (root)
695                 ret = root->m_OnAddAlbum(album, act);
696
697         return ret;
698 }
699
700 bool CEngine::m_OnAddAlbum(CBus::SAlbum *album, CBus::SAction *act)
701 {
702         CEngineBarItem *hit;
703         Eina_List *l;
704         void *obj;
705
706         if (!album || !act) {
707                 _ERR("Invalid argument");
708                 return -1;
709         }
710
711         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
712                 hit = (CEngineBarItem *)obj;
713                 if (strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), album->svcid))
714                         continue;
715
716                 return _add_dbar_item(hit, CEngineDBarItem::STYLE_ALBUM,
717                                 album->title, album->contents,
718                                 album->content_cnt,
719                                 act->action,
720                                 act->actor,
721                                 act->args);
722         }
723
724         return -1;
725 }
726
727 bool CEngine::sm_CbAddContent(CBus::SContent *content, CBus::SAction *act, void *data)
728 {
729         CEngine *root = (CEngine*)data;
730         bool ret = false;
731
732         if (root)
733                 ret = root->m_OnAddContent(content, act);
734
735         return ret;
736 }
737
738 bool CEngine::m_OnAddContent(CBus::SContent *content, CBus::SAction *act)
739 {
740         CEngineBarItem *hit;
741         Eina_List *l;
742         void *obj;
743
744         if (!content || !act) {
745                 _ERR("Invalid argument");
746                 return -1;
747         }
748
749         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
750                 hit = (CEngineBarItem *)obj;
751                 if (strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), content->svcid))
752                         continue;
753
754                 return _add_dbar_item(hit, CEngineDBarItem::STYLE_CONTENT,
755                                 content->title, content, 1,
756                                 act->action,
757                                 act->actor,
758                                 act->args);
759         }
760
761         return -1;
762 }
763
764 bool CEngine::sm_CbAddContents(Eina_List *list, void *data)
765 {
766         CEngine *root = (CEngine*)data;
767         bool ret = false;
768
769         if (root)
770                 return root->m_OnAddContents(list);
771
772         return ret;
773 }
774
775 bool CEngine::m_OnAddContents(Eina_List *list)
776 {
777         CBus::SContent *content;
778         CEngineBarItem *hit;
779         Eina_List *l, *ll;
780         void *obj;
781
782         if (!list) {
783                 _ERR("Invalid argument");
784                 return false;
785         }
786
787         EINA_LIST_FOREACH(list, l, obj) {
788                 content = (CBus::SContent *)obj;
789                 if (!content)
790                         continue;
791
792                 EINA_LIST_FOREACH(m->hbar_its, ll, obj) {
793                         hit = (CEngineBarItem *)obj;
794                         if (!strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), content->svcid)) {
795                                 _add_dbar_item(hit, CEngineDBarItem::STYLE_CONTENT,
796                                                 content->title, content, 1,
797                                                 content->action, content->actor, content->args);
798                         }
799                 }
800         }
801
802         return true;
803 }
804
805 static void _get_item_bg_and_icon(enum CBus::EPinType type, const char *icon,
806                 CEngineBarItem *it)
807 {
808         switch (type) {
809         case CBus::PIN_TYPE_PACKAGE:
810                 it->SetColor(ITEM_PACKAGE_BG_R, ITEM_PACKAGE_BG_G, ITEM_PACKAGE_BG_B);
811                 if (icon) {
812                         it->SetStr(CEngineBarItem::VSTR_ICON, icon);
813                         it->SetStr(CEngineBarItem::VSTR_ICON_FOCUS, icon);
814                 } else {
815                         it->SetStr(CEngineBarItem::VSTR_ICON, DEF_PIN_ITEM_DEFAULT_ICON);
816                         it->SetStr(CEngineBarItem::VSTR_ICON_FOCUS, DEF_PIN_ITEM_DEFAULT_ICON_FOCUS);
817                 }
818                 it->SetType(CAppContentFavorite::TYPE_APPS);
819                 break;
820         default:
821                 it->SetColor(ITEM_DEFAULT_BG_R, ITEM_DEFAULT_BG_G, ITEM_DEFAULT_BG_B);
822                 it->SetStr(CEngineBarItem::VSTR_ICON, DEF_PIN_ITEM_DEFAULT_ICON);
823                 it->SetStr(CEngineBarItem::VSTR_ICON_FOCUS, DEF_PIN_ITEM_DEFAULT_ICON_FOCUS);
824                 break;
825         }
826 }
827
828 CEngineBarItem *CEngineBarItem::Alloc(const char *title, CBus::EPinType type,
829                 const char *icon, const char *svcid,
830                 CBus::EActionOp action, const char *actor,
831                 const char *args, const char *pinid)
832 {
833         CEngineBarItem *it;
834
835         if (!title || !svcid || type > CBus::PIN_TYPE_MAX || !pinid)
836                 return NULL;
837
838         it = new CEngineBarItem;
839         if (!it) {
840                 _ERR("calloc failed");
841                 return NULL;
842         }
843
844         it->SetInt(CEngineBarItem::VINT_IS_PINNED, EINA_TRUE);
845         it->SetCtntId(it->CtntId() + 1);
846
847         it->SetStr(CEngineBarItem::VSTR_NAME, title);
848         it->SetStr(CEngineBarItem::VSTR_SVC_ID, svcid);
849         it->SetStr(CEngineBarItem::VSTR_IN, "custombar");
850         it->SetStr(CEngineBarItem::VSTR_PIN_ID, pinid);
851
852         _get_item_bg_and_icon(type, icon, it);
853
854         if (action == CBus::ACTION_OP_LAUNCH_APP)
855                 it->SetStr(CEngineBarItem::VSTR_APP, actor);// SetApp(actor);
856         if (args)
857                 it->SetStr(CEngineBarItem::VSTR_ARGS, args);// SetArgs(args);
858
859         return it;
860 }
861
862 void CEngine::_update_pin_list(void)
863 {
864         Eina_List *l;
865         CEngineBarItem *hit;
866         int size;
867         char *szContentId;
868         void *obj;
869
870         szContentId = NULL;
871
872         m->pAppContentPin->SetQuery(CAppContent::TYPE_ALL);
873         m->pAppContentPin->BeginQuery();
874
875         while (m->pAppContentPin->MoveNext()) {
876                 size = m->pAppContentPin->ContentIdSize();
877                 szContentId = new char[size];
878                 m->pAppContentPin->GetContentId(szContentId, size);
879
880                 EINA_LIST_FOREACH(m->pin_its, l, obj) {
881                         hit = (CEngineBarItem *)obj;
882                         if (!strcmp(hit->Str(CEngineBarItem::VSTR_PIN_ID), szContentId))
883                                 m->hbar_its = eina_list_append(m->hbar_its, hit);
884                 }
885
886         }
887
888         m->pAppContentPin->EndQuery();
889
890         m->is_full = EINA_TRUE;
891 }
892
893 int CEngine::_del_pin_item(Eina_Bool free)
894 {
895         CEngineBarItem *hit;
896         Eina_List *l;
897         void *obj;
898
899         if (!m->hbar_its)
900                 return -1;
901
902         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
903                 hit = (CEngineBarItem *)obj;
904                 if (!hit->Int(CEngineBarItem::VINT_IS_PINNED))
905                         continue;
906
907                 m->hbar_its = eina_list_remove_list(m->hbar_its, l);
908                 if (free)
909                         delete hit;
910         }
911
912         return 0;
913 }
914
915 bool CEngine::sm_CbAddPin(CBus::SPin *pin, CBus::SAction *act, void *data)
916 {
917         CEngine *root = (CEngine*)data;
918         bool ret = false;
919
920         if (root)
921                 ret = root->m_OnAddPin(pin, act);
922
923         return ret;
924 }
925
926 bool CEngine::m_OnAddPin(CBus::SPin *pin, CBus::SAction *act)
927 {
928         CEngineBarItem *hit;
929         Eina_List *l;
930         int cnt;
931         int r;
932         void *obj;
933
934         if (!pin || !act) {
935                 _ERR("Invalid argument");
936                 return false;
937         }
938
939         r = _del_pin_item(EINA_TRUE);
940         if (r < 0) {
941                 _ERR("failed to delete pin item in hbar list");
942                 return false;
943         }
944
945         if (m->is_full) {
946                 EINA_LIST_FOREACH(m->pin_its, l, obj) {
947                         hit = (CEngineBarItem *)obj;
948                         m->pin_its = eina_list_remove_list(m->pin_its, l);
949                 }
950                 m->is_full = EINA_FALSE;
951         }
952
953         hit = CEngineBarItem::Alloc(pin->title, pin->type, pin->icon, pin->svcid,
954                         act->action, act->actor, act->args, pin->pinid);
955         if (!hit)
956                 return false;
957
958         m->pin_its = eina_list_append(m->pin_its, hit);
959         cnt = eina_list_count(m->pin_its);
960
961         if (_get_pin_count() != cnt)
962                 return hit->CtntId();
963
964         _update_pin_list();
965
966         InvokeUpdateCallback();
967
968         return hit->CtntId();
969 }
970
971 bool CEngine::sm_CbDelContent(const char *svcid, int ctnt_id, void *data)
972 {
973         CEngine *root = (CEngine*)data;
974         bool ret = false;
975
976         if (root)
977                 ret = root->m_OnDelContent(svcid, ctnt_id);
978
979         return ret;
980 }
981
982 bool CEngine::m_OnDelContent(const char *svcid, int ctnt_id)
983 {
984         CEngineBarItem *hit;
985         Eina_List *l;
986         void *obj;
987
988         if (!svcid || ctnt_id < 0) {
989                 _ERR("Invalid argument");
990                 return false;
991         }
992
993         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
994                 hit = (CEngineBarItem *)obj;
995                 if (strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), svcid))
996                         continue;
997                 return _del_dbar_item(hit, ctnt_id);
998         }
999
1000         return false;
1001 }
1002
1003 bool CEngine::sm_CbDelAll(const char *svcid, bool reload, void *data)
1004 {
1005         CEngine *root = (CEngine*)data;
1006         bool ret = false;
1007
1008         if (root)
1009                 ret = root->m_OnDelAll(svcid, reload);
1010
1011         return ret;
1012 }
1013
1014 bool CEngine::m_OnDelAll(const char *svcid, bool reload)
1015 {
1016         CEngineBarItem *hit;
1017         Eina_List *l;
1018         void *obj;
1019
1020         if (!svcid) {
1021                 _ERR("Invalid argument");
1022                 return false;
1023         }
1024
1025         if (reload) {
1026                 _del_pin_item(EINA_TRUE);
1027
1028                 InvokeUpdateCallback();
1029                 return true;
1030         }
1031
1032         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
1033                 hit = (CEngineBarItem *)obj;
1034                 if (strcmp(hit->Str(CEngineBarItem::VSTR_SVC_ID), svcid))
1035                         continue;
1036                 return _del_dbar_item_all(hit);
1037         }
1038
1039         return false;
1040 }
1041
1042 bool CEngine::Create(void)
1043 {
1044         ASSERT(!m);
1045
1046         CBus::SCallback cb;
1047         cb.cbReady      = sm_CbBusReady;
1048         cb.cbEnd        = sm_CbBusEnd;
1049
1050         cb.cbAddLabel   = sm_CbAddLabel;
1051         cb.cbAddAlbum   = sm_CbAddAlbum;
1052         cb.cbAddContent = sm_CbAddContent;
1053         cb.cbAddContents = sm_CbAddContents;
1054         cb.cbAddPin     = sm_CbAddPin;
1055
1056         cb.cbDelContent = sm_CbDelContent;
1057         cb.cbDelAll = sm_CbDelAll;
1058         cb.cookie = this;
1059
1060         _CREATE_BEGIN{
1061                 _CHECK(m = new SEngine);
1062                 _CHECK(m_LoadUser());
1063                 _CHECK(m_LoadItemConfig());
1064                 _CHECK(m->bus = new CBus);
1065                 _CHECK(m->bus->Create(&cb));
1066                 _CHECK(m->pAppContentFavorite = new CAppContentFavorite);
1067                 _CHECK(m->pAppContentFavorite->Create(NULL));
1068                 _CHECK(m->pAppContentHistory = new CAppContentHistory);
1069                 _CHECK(m->pAppContentHistory->Create(NULL));
1070                 _CHECK(m->pAppContentPin = new CAppContentPin);
1071                 _CHECK(m->pAppContentPin->Create(NULL));
1072
1073
1074                 _CHECK_FAIL{ m->pAppContentPin->Destroy(); }
1075                 _CHECK_FAIL{ delete m->pAppContentPin; }
1076                 _CHECK_FAIL{ m->pAppContentHistory->Destroy(); }
1077                 _CHECK_FAIL{ delete m->pAppContentHistory; }
1078                 _CHECK_FAIL{ m->pAppContentFavorite->Destroy(); }
1079                 _CHECK_FAIL{ delete m->pAppContentFavorite; }
1080                 _CHECK_FAIL{ m->bus->Destroy(); }
1081                 _CHECK_FAIL{ delete m->bus; }
1082                 _CHECK_FAIL{ m_UnloadConfig(); }
1083                 _CHECK_FAIL{ /* m_LOadUser */ }
1084                 _CHECK_FAIL{ delete m; m = NULL; }
1085         } _CREATE_END_AND_CATCH{ return false; }
1086
1087         return true;
1088 }
1089
1090 void CEngine::Destroy(void)
1091 {
1092         ASSERT(m);
1093
1094         CClientBus *cbus;
1095         void *obj;
1096
1097         m->pAppContentPin->Destroy();
1098         delete m->pAppContentPin;
1099
1100         m->pAppContentFavorite->Destroy();
1101         delete m->pAppContentFavorite;
1102
1103         m->pAppContentHistory->Destroy();
1104         delete m->pAppContentHistory;
1105
1106         m_UnloadConfig();
1107         m->bus->Destroy();
1108         delete m->bus;
1109         EINA_LIST_FREE(m->client_buslist, obj) {
1110                 cbus = (CClientBus *)obj;
1111                 cbus->Destroy();
1112                 delete cbus;
1113         }
1114
1115         delete m;
1116         m = NULL;
1117 }
1118
1119 bool CEngine::GetUserInfo(const char **name, const char **thumb_bg, const char **thumb)
1120 {
1121         ASSERT(m);
1122
1123         if (name)
1124                 *name = m->user.name;
1125         if (thumb_bg)
1126                 *thumb_bg = m->user.thumb_bg;
1127         if (thumb)
1128                 *thumb = m->user.thumb;
1129
1130         return true;
1131 }
1132
1133 const Eina_List *CEngine::BarItemsList(void)
1134 {
1135         ASSERT(m);
1136
1137         return m->hbar_its;
1138 }
1139
1140 void CEngine::SetUpdateCallback(void (*update_cb)(void *data, bool focus), void *data)
1141 {
1142         ASSERT(m);
1143
1144         m->update_cb = update_cb;
1145         m->update_cb_data = data;
1146 }
1147
1148 void CEngine::InvokeUpdateCallback(void)
1149 {
1150         ASSERT(m);
1151
1152         if (m->update_cb)
1153                 m->update_cb(m->update_cb_data, true);
1154 }
1155
1156 bool CEngine::GetPrivilege(void)
1157 {
1158         ASSERT(m);
1159
1160         int r;
1161         cynara *p_cynara;
1162
1163         p_cynara = NULL;
1164         r = cynara_initialize(&p_cynara, NULL);
1165         if (r != CYNARA_API_SUCCESS || !p_cynara) {
1166                 _ERR("failed to initialize cynara");
1167                 return false;
1168         }
1169
1170         r = cynara_check(p_cynara, "User", "", m->user.name,
1171                         "user_label.write");
1172         if (r != CYNARA_API_ACCESS_ALLOWED) {
1173                 _ERR("cyana denied, %d", r);
1174                 return false;
1175         }
1176
1177         cynara_finish(p_cynara);
1178
1179         return true;
1180 }
1181
1182 bool CEngine::Delete(CEngineUBarItem *it, const char *password)
1183 {
1184         ASSERT(m);
1185
1186         Eina_List *l;
1187         GumUser *user;
1188         gboolean r;
1189         CEngineUBarItem *_it;
1190         void *obj;
1191
1192         if (!it || !password) {
1193                 _ERR("Invalid argument");
1194                 return false;
1195         }
1196
1197         user = gum_user_get_by_name_sync(it->Str(CEngineUBarItem::VSTR_NAME), FALSE);
1198         if (!user) {
1199                 _ERR("failed to get user");
1200                 return false;
1201         }
1202
1203         r = gum_user_delete_sync(user, FALSE);
1204         if (!r) {
1205                 _ERR("failed to delete user");
1206                 g_object_unref(user);
1207                 return false;
1208         }
1209
1210         EINA_LIST_FOREACH(m->ubar_its, l, obj) {
1211                 _it = (CEngineUBarItem *)obj;
1212                 if (strcmp(_it->Str(CEngineUBarItem::VSTR_NAME), it->Str(CEngineUBarItem::VSTR_NAME)))
1213                         continue;
1214
1215                 m->ubar_its = eina_list_remove_list(m->ubar_its, l);
1216                 free(_it);
1217         }
1218
1219         g_object_unref(user);
1220
1221         return true;
1222 }
1223
1224 const Eina_List *CEngine::UBarItemsList(void)
1225 {
1226         ASSERT(m);
1227
1228         return m->ubar_its;
1229 }
1230
1231
1232 bool CEngine::DelAllHistory(void)
1233 {
1234         ASSERT(m);
1235
1236         if (!m->pAppContentHistory->RemoveAll()) {
1237                 _ERR("failed to remove all history");
1238                 return false;
1239         }
1240
1241         return true;
1242 }
1243
1244
1245 bool CEngine::DelHistory(CAppContent::EType type, const char *id)
1246 {
1247         ASSERT(m);
1248
1249         if (!id)
1250                 return false;
1251
1252         if (!m->pAppContentHistory->Remove(type, id)) {
1253                 _ERR("failed to remove history");
1254                 return false;
1255         }
1256
1257         return true;
1258 }
1259
1260
1261 bool CEngine::AddHistory(CAppContent::EType type, const char *id)
1262 {
1263         ASSERT(m);
1264
1265         if (!id)
1266                 return false;
1267
1268         if (!m->pAppContentHistory->Add(type, id)) {
1269                 _ERR("failed to add history");
1270                 return false;
1271         }
1272
1273         return true;
1274 }
1275
1276
1277 bool CEngine::DelPin(CEngineBarItem *it)
1278 {
1279         ASSERT(m);
1280
1281         Eina_List *l;
1282         CEngineBarItem *hit;
1283         void *obj;
1284
1285         if (!it)
1286                 return false;
1287
1288         if (!m->pAppContentPin->Remove(it->Type(), it->Str(CEngineBarItem::VSTR_PIN_ID))) {
1289                 _ERR("failed to unset pin item");
1290                 return false;
1291         }
1292
1293         if (_get_pin_count() != 0)
1294                 return true;
1295
1296         EINA_LIST_FOREACH(m->hbar_its, l, obj) {
1297                 hit = (CEngineBarItem *)obj;
1298                 if (!hit->Str(CEngineBarItem::VSTR_PIN_ID))
1299                         continue;
1300
1301                 if (!strcmp(hit->Str(CEngineBarItem::VSTR_PIN_ID), it->Str(CEngineBarItem::VSTR_PIN_ID))) {
1302                         m->hbar_its = eina_list_remove_list(m->hbar_its, l);
1303                         delete hit;
1304                         break;
1305                 }
1306         }
1307
1308         return true;
1309 }
1310
1311 void CEngine::AddUBar(CEngineUBarItem *it)
1312 {
1313         ASSERT(m);
1314
1315         m->ubar_its = eina_list_append(m->ubar_its, it);
1316 }
1317
1318 bool CEngine::Swap(CEngineBarItem *it1, CEngineBarItem *it2)
1319 {
1320         ASSERT(it1);
1321         ASSERT(it2);
1322
1323         if (!it1->Str(CEngineBarItem::VSTR_PIN_ID) || !it2->Str(CEngineBarItem::VSTR_PIN_ID)) {
1324                 _ERR("No pin item");
1325                 return false;
1326         }
1327
1328         if (!m->pAppContentPin->Swap(it1->Type(), (char *)it1->Str(CEngineBarItem::VSTR_PIN_ID),
1329                                 it2->Type(), (char *)it2->Str(CEngineBarItem::VSTR_PIN_ID))) {
1330                 _ERR("failed to swap content");
1331                 return false;
1332         }
1333
1334         _del_pin_item(EINA_FALSE);
1335         _update_pin_list();
1336
1337         return true;
1338 }
1339
1340
1341 int CEngine::_get_pin_count(void)
1342 {
1343         ASSERT(m);
1344
1345         int r = 0;
1346
1347         m->pAppContentPin->SetQuery(CAppContent::TYPE_ALL);
1348         m->pAppContentPin->BeginQuery();
1349
1350         while (m->pAppContentPin->MoveNext())
1351                 r++;
1352
1353         m->pAppContentPin->EndQuery();
1354
1355         return r;
1356 }