8722b960a658b612f8d29043c875933c27bb28e3
[platform/core/appfw/app-svc.git] / src / appsvc.c
1 /*
2  *  app-svc
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <glib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29
30 #include <aul.h>
31 #include <libsoup/soup.h>
32
33 #ifndef WAYLAND
34 #include <Ecore_X.h>
35 #endif
36
37 #include <Ecore.h>
38 #include <iniparser.h>
39 #include <pkgmgr-info.h>
40 #include <tzplatform_config.h>
41
42 #include "appsvc.h"
43 #include "appsvc_db.h"
44 #include "internal.h"
45 #include "priv_key.h"
46
47
48
49 #ifndef SLPAPI
50 #define SLPAPI __attribute__ ((visibility("default")))
51 #endif
52
53
54 /* callback handling */
55 typedef struct _appsvc_cb_info_t{
56         appsvc_res_fn cb_func;
57         int request_code;
58         void *data;
59 }appsvc_cb_info_t;
60
61 typedef struct _appsvc_resolve_info_t{
62         char *pkgname;
63         char *op;
64         char *uri;
65         char *scheme;
66         char *host;
67         char *uri_r_info;
68         char *origin_mime;
69         char *mime;     
70         char *m_type;
71         char *s_type;
72         char *category;
73         char *win_id;
74         int mime_set;
75 }appsvc_resolve_info_t;
76
77 extern int aul_launch_app_with_result(const char *pkgname, bundle *kb,
78                                void (*cbfunc) (bundle *, int, void *),
79                                void *data);
80
81 static appsvc_cb_info_t *__create_rescb(int request_code, appsvc_res_fn cbfunc,
82                                         void *data);
83 static void __remove_rescb(appsvc_cb_info_t *info);
84 static int __set_bundle(bundle *b, const char *key, const char *value);
85 static void __aul_cb(bundle *b, int is_cancel, void *data);
86 static int __run_svc_with_pkgname(char *pkgname, bundle *b, int request_code,
87                                   appsvc_res_fn cbfunc, void *data);
88 static int __get_resolve_info(bundle *b, appsvc_resolve_info_t *info);
89 static int __free_resolve_info_data(appsvc_resolve_info_t *info);
90 static int __get_list_with_condition(char *op, char *uri,
91                                      char *mime, GSList **pkg_list, uid_t uid);
92
93
94 static appsvc_cb_info_t *__create_rescb(int request_code, appsvc_res_fn cbfunc, void *data)
95 {
96         appsvc_cb_info_t* info;
97
98         info = (appsvc_cb_info_t*)calloc(1, sizeof(appsvc_cb_info_t));
99         if(info == NULL)
100                 return NULL;
101
102         info->request_code = request_code;
103         info->cb_func = cbfunc;
104         info->data = data;
105
106         return info;
107 }
108
109 static void __remove_rescb(appsvc_cb_info_t *info)
110 {
111         if(info) free(info);
112 }
113
114 static int __set_bundle(bundle *b, const char *key, const char *value)
115 {
116         const char *val = NULL;
117
118         val = bundle_get_val(b, key);
119         if(val){
120                 if( bundle_del(b, key) != 0 ){
121                         return APPSVC_RET_ERROR;
122                 }
123         }
124
125         if(!value) 
126                 return APPSVC_RET_EINVAL;
127                 
128         if( bundle_add(b, key, value) != 0 ){
129                 return APPSVC_RET_ERROR;
130         }
131
132         _D("__set_bundle");
133 //      bundle_iterate(b, __bundle_iterate, NULL);
134
135         return APPSVC_RET_OK;
136 }
137
138 static int __set_bundle_array(bundle *b, const char *key, const char **value, int len)
139 {
140
141         int type;
142         type = appsvc_data_is_array(b, key);
143
144         if(type == 1) {
145                 if( bundle_del(b, key) != 0 ){
146                         return APPSVC_RET_ERROR;
147                 }
148         }
149
150         if(!value) 
151                 return APPSVC_RET_EINVAL;
152
153         if( bundle_add_str_array(b, key, value, len) != 0 ){
154                 return APPSVC_RET_ERROR;
155         }
156
157         _D("__set_bundle_array");
158 //      bundle_iterate(b, __bundle_iterate, NULL);
159
160         return APPSVC_RET_OK;
161 }
162
163
164 static void __aul_cb(bundle *b, int is_cancel, void *data)
165 {
166         const char *val = NULL;
167         appsvc_cb_info_t*  cb_info;
168         int res;
169
170         if(is_cancel)
171                 res = APPSVC_RES_CANCEL;
172         else{
173                 /* get result_code from bundle */
174                 val = bundle_get_val(b, APP_SVC_K_RES_VAL);
175                 res = (val==NULL)? APPSVC_RES_NOT_OK : atoi(val);
176         }
177
178         /* remove result_code from bundle */
179         bundle_del(b, APP_SVC_K_RES_VAL);
180
181         /* find corresponding callback */
182         cb_info = (appsvc_cb_info_t*)data;
183         
184         cb_info->cb_func(b, cb_info->request_code, (appsvc_result_val)res, cb_info->data);
185         __remove_rescb(cb_info);
186         
187
188         return;
189 }
190
191 static int __run_svc_with_pkgname(char *pkgname, bundle *b, int request_code, appsvc_res_fn cbfunc, void *data)
192 {
193         appsvc_cb_info_t *cb_info = NULL;
194         int ret = -1;
195         
196         if (cbfunc) {
197                 _D("pkg_name : %s - with result", pkgname);
198
199                 cb_info = __create_rescb(request_code, cbfunc, data);
200                 ret = aul_launch_app_with_result(pkgname, b, __aul_cb, cb_info);
201         } else {
202                 _D("pkg_name : %s - no result", pkgname);
203                 ret = aul_launch_app(pkgname, b);
204         }
205
206         if(ret < 0) {
207                 switch (ret) {
208                         case AUL_R_EILLACC:
209                                 ret = APPSVC_RET_EILLACC;
210                                 break;
211                         case AUL_R_EINVAL:
212                                 ret = APPSVC_RET_EINVAL;
213                                 break;
214                         case AUL_R_ENOAPP:
215                                 ret = APPSVC_RET_ENOMATCH;
216                                 break;
217                         default:
218                                 ret = APPSVC_RET_ELAUNCH;
219                 }
220         }
221
222         return ret;
223 }
224
225 static int __get_resolve_info(bundle *b, appsvc_resolve_info_t *info)
226 {
227         char *tmp = NULL;
228         char *strtok_buf = NULL;
229         SoupURI *s_uri;
230         
231         info->op = (char *)appsvc_get_operation(b);
232         info->uri = (char *)appsvc_get_uri(b);
233         info->origin_mime = info->mime = (char *)appsvc_get_mime(b);
234         info->pkgname = (char *)appsvc_get_pkgname(b);
235         info->category = (char *)appsvc_get_category(b);
236         info->win_id = (char *)bundle_get_val(b, APP_SVC_K_WIN_ID);
237
238         if(info->uri) {
239                 if(strncmp(info->uri,"/",1) == 0){
240                         if(!info->mime) {
241                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
242                                 aul_get_mime_from_file(info->uri, info->mime, MAX_MIME_STR_SIZE);
243                                 info->mime_set = 1;
244                         }
245                         info->uri = NULL;                       
246                 } else if(strncmp(info->uri,"file:/",6)==0){
247                         if(!info->mime) {
248                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
249                                 aul_get_mime_from_file(&info->uri[5], info->mime, MAX_MIME_STR_SIZE);
250                                 info->mime_set = 1;
251                         }
252                         info->uri = NULL;
253                 } else if(strncmp(info->uri,"file:///",8) == 0){
254                         if(!info->mime) {
255                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
256                                 aul_get_mime_from_file(&info->uri[7], info->mime, MAX_MIME_STR_SIZE);   
257                                 info->mime_set = 1;
258                         }
259                         info->uri = NULL;
260                 }
261         }
262
263         if(info->uri) {
264                 s_uri = soup_uri_new(info->uri);
265
266                 if(!s_uri)
267                         return APPSVC_RET_EINVAL;
268
269                 if(s_uri->scheme) {
270                         info->scheme = malloc(MAX_SCHEME_STR_SIZE);
271                         strncpy(info->scheme, s_uri->scheme, MAX_SCHEME_STR_SIZE-1);
272                 }
273                 if(s_uri->host) {
274                         info->host = malloc(MAX_HOST_STR_SIZE);
275                         strncpy(info->host, s_uri->host, MAX_HOST_STR_SIZE-1);
276                 }
277                 if(info->scheme && info->host) {
278                         info->uri_r_info = malloc(MAX_SCHEME_STR_SIZE+MAX_HOST_STR_SIZE+2);
279                         snprintf(info->uri_r_info, MAX_SCHEME_STR_SIZE+MAX_HOST_STR_SIZE+1,
280                                 "%s://%s", info->scheme, info->host);
281                 }
282
283                 soup_uri_free(s_uri);
284         } else {
285                 info->scheme = strdup("NULL");
286         }
287
288         if(!info->mime) 
289                 info->mime = strdup("NULL");
290         else {
291                 info->m_type = malloc(MAX_LOCAL_BUFSZ);
292                 info->s_type = malloc(MAX_LOCAL_BUFSZ);
293                 tmp = strdup(info->mime);
294                 strtok_buf = strtok(tmp,"/");
295                 if(strtok_buf)
296                         strncpy(info->m_type, strtok_buf, MAX_LOCAL_BUFSZ-1);
297                 strtok_buf = strtok(NULL,"/");
298                 if(strtok_buf)
299                         strncpy(info->s_type, strtok_buf, MAX_LOCAL_BUFSZ-1);
300                 free(tmp);
301
302                 if(strncmp(info->m_type, "*", 1) == 0) {
303                         strncpy(info->m_type, "%", MAX_LOCAL_BUFSZ-1);
304                 }
305                 if(strncmp(info->s_type, "*", 1) == 0) {
306                         strncpy(info->s_type, "%", MAX_LOCAL_BUFSZ-1);  
307                 }
308
309                 info->mime = malloc(MAX_MIME_STR_SIZE);
310                 snprintf(info->mime, MAX_MIME_STR_SIZE-1, "%s/%s", info->m_type, info->s_type);
311         }
312
313         return 0;
314 }
315
316 static int __free_resolve_info_data(appsvc_resolve_info_t *info)
317 {
318         if (info->mime) 
319                 free(info->mime);
320         if (info->scheme) 
321                 free(info->scheme);
322         if (info->host)
323                 free(info->host);
324         if (info->m_type)
325                 free(info->m_type);
326         if (info->s_type)
327                 free(info->s_type);
328         if (info->uri_r_info)
329                 free(info->uri_r_info);
330         if (info->mime_set)
331                 free(info->origin_mime);
332         
333         return 0;
334 }
335
336 SLPAPI int appsvc_set_operation(bundle *b, const char *operation)
337 {       
338         if(b == NULL){
339                 _E("bundle for appsvc_set_operation is NULL");
340                 return APPSVC_RET_EINVAL;
341         }
342
343         return __set_bundle(b, APP_SVC_K_OPERATION, operation);
344 }
345
346 SLPAPI int appsvc_set_uri(bundle *b, const char *uri)
347 {       
348         if(b == NULL){
349                 _E("bundle for appsvc_set_uri is NULL");
350                 return APPSVC_RET_EINVAL;
351         }
352         
353         return __set_bundle(b, APP_SVC_K_URI, uri);
354 }
355
356 SLPAPI int appsvc_set_mime(bundle *b, const char *mime)
357 {       
358         if(b == NULL){
359                 _E("bundle for appsvc_set_mime is NULL");
360                 return APPSVC_RET_EINVAL;
361         }
362
363         return __set_bundle(b, APP_SVC_K_MIME, mime);
364 }
365
366 SLPAPI int appsvc_add_data(bundle *b, const char *key, const char *val)
367 {
368         if(b == NULL || key == NULL) {
369                 return APPSVC_RET_EINVAL;
370         }
371
372         /* check key for data */
373         /******************/
374
375         return __set_bundle(b, key, val);
376 }
377
378 SLPAPI int appsvc_add_data_array(bundle *b, const char *key,  const char **val_array, int len)
379 {
380         if(b == NULL || key == NULL) {
381                 return APPSVC_RET_EINVAL;
382         }
383
384         /* check key for data */
385         /******************/
386
387         return __set_bundle_array(b, key, val_array, len);
388 }
389
390
391 SLPAPI int appsvc_set_pkgname(bundle *b, const char *pkg_name)
392 {       
393         if(b == NULL){
394                 _E("bundle for appsvc_set_pkgname is NULL");
395                 return APPSVC_RET_EINVAL;
396         }
397
398         return __set_bundle(b, APP_SVC_K_PKG_NAME, pkg_name);
399 }
400
401 static char* __get_alias_appid(char *appid)
402 {
403         char *alias_id = NULL;
404         char *val = NULL;
405         char key_string[MAX_PACKAGE_STR_SIZE+5];
406         dictionary *dic;
407
408         dic = iniparser_load("/usr/share/appsvc/alias.ini");
409
410         if(dic == NULL)
411                 return NULL;
412
413         sprintf(key_string, "Alias:%s", appid);
414         val = iniparser_getstring(dic, key_string, NULL);
415
416         _D("alias_id : %s", val);
417
418         if(val != NULL) {
419                 alias_id = malloc(MAX_PACKAGE_STR_SIZE);
420                 strncpy(alias_id, val, MAX_PACKAGE_STR_SIZE-1);
421         }
422
423         iniparser_freedict(dic);
424
425         return alias_id;
426 }
427
428 SLPAPI int appsvc_set_appid(bundle *b, const char *appid)
429 {
430         char *alias_id = NULL;
431         int ret;
432
433         if(b == NULL || appid == NULL){
434                 _E("bundle for appsvc_set_appid is NULL");
435                 return APPSVC_RET_EINVAL;
436         }
437
438         alias_id = __get_alias_appid(appid);
439         if(alias_id == NULL) {
440                 ret = __set_bundle(b, APP_SVC_K_PKG_NAME, appid);
441         } else {
442                 ret = __set_bundle(b, APP_SVC_K_PKG_NAME, alias_id);
443                 free(alias_id);
444         }
445
446         return ret;
447 }
448
449 SLPAPI int appsvc_set_category(bundle *b, const char *category)
450 {
451         if(b == NULL){
452                 _E("bundle for appsvc_set_category is NULL");
453                 return APPSVC_RET_EINVAL;
454         }
455
456         return __set_bundle(b, APP_SVC_K_CATEGORY, category);
457 }
458
459 SLPAPI int appsvc_set_launch_mode(bundle *b, const char *mode)
460 {
461         if (b == NULL) {
462                 _E("bundle for appsvc_set_launch_mode is NULL");
463                 return APPSVC_RET_EINVAL;
464         }
465
466         return __set_bundle(b, APP_SVC_K_LAUNCH_MODE, mode);
467 }
468 static int __get_list_with_condition_mime_extened(char *op, char *uri, char *mime,
469        char *m_type, char *s_type, GSList **pkg_list, uid_t uid)
470 {
471         char *tmp;
472
473         tmp = malloc(MAX_MIME_STR_SIZE);
474
475         _svc_db_get_list_with_condition(op, uri, mime, pkg_list, uid);
476         if ((strncmp(mime, "NULL", 4) != 0) && (strncmp(s_type, "%", 1) != 0)) {
477                 snprintf(tmp, MAX_MIME_STR_SIZE-1, "%s/*", m_type);
478                 _svc_db_get_list_with_condition(op, uri, tmp, pkg_list, uid);
479         }
480         if ((strncmp(mime, "NULL", 4) != 0) && (strncmp(m_type, "%", 1) != 0)) {
481                 snprintf(tmp, MAX_MIME_STR_SIZE-1, "*/*");
482                 _svc_db_get_list_with_condition(op, uri, tmp, pkg_list, uid);
483         }
484         free(tmp);
485
486         return 0;
487 }
488
489 static int __get_list_with_condition_mime_extened_with_collation(char *op, char *uri, char *mime,
490         char *m_type, char *s_type, GSList **pkg_list, uid_t uid)
491 {
492         char *tmp;
493
494         tmp = malloc(MAX_MIME_STR_SIZE);
495
496         _svc_db_get_list_with_collation(op, uri, mime, pkg_list, uid);
497         if ((strncmp(mime, "NULL", 4) != 0) && (strncmp(s_type, "%", 1) != 0)) {
498                 snprintf(tmp, MAX_MIME_STR_SIZE-1, "%s/*", m_type);
499                 _svc_db_get_list_with_collation(op, uri, tmp, pkg_list, uid);
500         }
501         if ((strncmp(mime, "NULL", 4) != 0) && (strncmp(m_type, "%", 1) != 0)) {
502                 snprintf(tmp, MAX_MIME_STR_SIZE-1, "*/*");
503                 _svc_db_get_list_with_collation(op, uri, tmp, pkg_list, uid);
504         }
505         free(tmp);
506
507         return 0;
508 }
509
510 GSList *tmp_list;
511 static int __app_list_cb(pkgmgrinfo_appinfo_h handle, void *user_data)
512 {
513         char *appid = NULL;
514         GSList **app_list = (GSList **)user_data;
515         char *str = NULL;
516         GSList *iter = NULL;
517
518         pkgmgrinfo_appinfo_get_appid(handle, &str);
519         _D("Matching application is %s",str);
520
521         for (iter = tmp_list; iter != NULL; iter = g_slist_next(iter)) {
522                 if (strncmp(str, (char *)iter->data, MAX_PACKAGE_STR_SIZE-1) == 0) {
523                         appid = strdup(str);
524                         *app_list = g_slist_append(*app_list, (void *)appid);
525                         _D("%s is added",appid);
526                 }
527         }
528
529         return 0;
530 }
531
532 static int __get_list_with_category(char *category, GSList **pkg_list, uid_t uid)
533 {
534         int ret;
535         pkgmgrinfo_appinfo_filter_h handle;
536         GSList *app_list = NULL;
537         GSList *iter = NULL;
538         char *list_item = NULL;
539
540         ret = pkgmgrinfo_appinfo_filter_create(&handle);
541         ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, category);
542
543         tmp_list = *pkg_list;
544         ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(handle, __app_list_cb, &app_list, uid);
545         if (ret != PMINFO_R_OK) {
546                 pkgmgrinfo_appinfo_filter_destroy(handle);
547                 return -1;
548         }
549         pkgmgrinfo_appinfo_filter_destroy(handle);
550
551         for (iter = *pkg_list; iter != NULL; iter = g_slist_next(iter)) {
552                 list_item = (char *)iter->data;
553                 g_free(list_item);
554         }
555         g_slist_free(*pkg_list);
556
557         *pkg_list = app_list;
558
559         return 0;
560 }
561
562 static int __appid_compare(gconstpointer data1, gconstpointer data2)
563 {
564         char *a = (char *)data1;
565         char *b = (char *)data2;
566         return strcmp(a,b);
567 }
568
569 static int __get_list_with_submode(char *win_id, GSList **pkg_list, uid_t uid)
570 {
571         int ret;
572         GSList *iter = NULL;
573         char *appid = NULL;
574         GSList *find_item = NULL;
575         char *find_appid = NULL;
576         pkgmgrinfo_appinfo_h handle = NULL;
577         char *submode_mainid = NULL;
578
579 #ifndef WAYLAND
580         for (iter = *pkg_list; iter != NULL; ) {
581                 find_item = NULL;
582                 submode_mainid = NULL;
583                 appid = (char *)iter->data;
584                 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
585                 SECURE_LOGD("ret %d, %s, %x", ret, appid, handle);
586                 ret = pkgmgrinfo_appinfo_get_submode_mainid(handle, &submode_mainid);
587                 SECURE_LOGD("appid(%s) submode_mainid(%s) win_id(%s)", appid, submode_mainid, win_id);
588                 if(submode_mainid) {
589                         if(win_id) {
590                                 find_item = g_slist_find_custom(*pkg_list, submode_mainid, __appid_compare);
591                                 if(find_item) {
592                                         find_appid = find_item->data;
593                                         if(find_item == g_slist_next(iter)) {
594                                                 iter = g_slist_next(find_item);
595                                                 *pkg_list = g_slist_remove(*pkg_list, find_appid);
596                                                 free(find_appid);
597                                         } else {
598                                                 iter = g_slist_next(iter);
599                                                 *pkg_list = g_slist_remove(*pkg_list, find_appid);
600                                                 free(find_appid);
601                                         }
602                                 }
603                         } else {
604                                 find_item = g_slist_find_custom(*pkg_list, submode_mainid, __appid_compare);
605                                 if(find_item) {
606                                         iter = g_slist_next(iter);
607                                         *pkg_list = g_slist_remove(*pkg_list, appid);
608                                         free(appid);
609                                 }
610                         }
611                 }
612                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
613                 if(!find_item) {
614                         iter = g_slist_next(iter);
615                 }
616         }
617 #endif
618
619         for (iter = *pkg_list; iter != NULL; iter = g_slist_next(iter)) {
620                 appid = (char *)iter->data;
621                 SECURE_LOGD("appid(%s)", appid);
622         }
623
624         return 0;
625 }
626
627 SLPAPI int appsvc_run_service(bundle *b, int request_code, appsvc_res_fn cbfunc, void *data)
628 {
629         //using default user to allow app-svc API usage  for deamon.
630         //App-svc run service leads to app launch that could require a graphical session.
631         //Indeed bluetooth_agent uses this API and is launched as bluetooth user (that not regular user).
632         return appsvc_usr_run_service(b, request_code, cbfunc, data, tzplatform_getuid(TZ_SYS_DEFAULT_USER));
633 }
634
635 SLPAPI int appsvc_usr_run_service(bundle *b, int request_code, appsvc_res_fn cbfunc, void *data, uid_t uid)
636 {
637         appsvc_resolve_info_t info;
638         char *pkgname;
639         int pkg_count = 0;
640         int ret = -1;
641
642         GSList *pkg_list = NULL;
643         GSList *iter = NULL;
644         char *list_item;
645
646         if(b == NULL){
647                 _E("bundle for appsvc_set_appid is NULL");
648                 return APPSVC_RET_EINVAL;
649         }
650
651         pkgname = (char *)appsvc_get_pkgname(b);
652
653         /* explict*/
654         if(pkgname) {
655                 if(appsvc_get_operation(b) == NULL)
656                         appsvc_set_operation(b,APPSVC_OPERATION_DEFAULT);
657                 ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
658                 return ret;
659         }
660
661         memset(&info, 0, sizeof(appsvc_resolve_info_t));
662         ret = __get_resolve_info(b, &info);
663         if(ret < 0)
664                 return ret;
665
666         _D("op - %s / mime - %s / scheme - %s\n", info.op, info.origin_mime, info.scheme);
667
668         /*uri*/
669         pkgname = _svc_db_get_app(info.op, info.origin_mime, info.uri, uid);
670         if(pkgname==NULL){
671                 __get_list_with_condition_mime_extened_with_collation(info.op, info.uri,
672                                 info.mime, info.m_type, info.s_type, &pkg_list, uid);
673                 pkg_count = g_slist_length(pkg_list);
674                 if(pkg_count > 0) {
675
676                         if(info.uri_r_info) {
677                                 __get_list_with_condition_mime_extened(info.op, info.uri_r_info,
678                                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
679                         }
680
681                         __get_list_with_condition_mime_extened(info.op, info.scheme,
682                                 info.mime, info.m_type, info.s_type, &pkg_list, uid);
683
684                         __get_list_with_condition_mime_extened(info.op, "*",
685                                 info.mime, info.m_type, info.s_type, &pkg_list, uid);
686
687                         if(info.category) {
688                                 __get_list_with_category(info.category, &pkg_list, uid);
689                         }
690
691                         __get_list_with_submode(info.win_id, &pkg_list, uid);
692
693                         pkg_count = g_slist_length(pkg_list);
694                         _D("pkg_count : %d", pkg_count);
695
696                         if(pkg_count == 1){
697                                 pkgname = (char *)pkg_list->data;
698                                 if(pkgname != NULL){
699                                         ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
700                                         goto end;
701                                 }
702                         } else {
703                                 bundle_add(b, APP_SVC_K_URI_R_INFO, info.uri);
704                                 ret = __run_svc_with_pkgname(APP_SELECTOR, b, request_code, cbfunc, data);
705                                 goto end;
706                         }
707                         for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
708                                 list_item = (char *)iter->data;
709                                 g_free(list_item);
710                         }
711                         g_slist_free(pkg_list);
712                         pkg_list = NULL;
713                 }
714         } else {
715                 ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
716                 free(pkgname);
717                 goto end;
718         }
719
720         /*scheme & host*/
721         if(info.uri_r_info) {
722                 pkgname = _svc_db_get_app(info.op, info.origin_mime, info.uri_r_info, uid);
723
724                 if(pkgname==NULL){
725                         __get_list_with_condition_mime_extened(info.op, info.uri_r_info,
726                                 info.mime, info.m_type, info.s_type, &pkg_list, uid);
727                         pkg_count = g_slist_length(pkg_list);
728                         if(pkg_count > 0) {
729                                 __get_list_with_condition_mime_extened(info.op, info.scheme,
730                                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
731
732                                 __get_list_with_condition_mime_extened(info.op, "*",
733                                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
734
735                                 if(info.category) {
736                                         __get_list_with_category(info.category, &pkg_list, uid);
737                                 }
738
739                                 __get_list_with_submode(info.win_id, &pkg_list, uid);
740
741                                 pkg_count = g_slist_length(pkg_list);
742                                 _D("pkg_count : %d", pkg_count);
743
744                                 if(pkg_count == 1){
745                                         pkgname = (char *)pkg_list->data;
746                                         if(pkgname != NULL){
747                                                 ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
748                                                 goto end;
749                                         }
750                                 } else {
751                                         bundle_add(b, APP_SVC_K_URI_R_INFO, info.uri_r_info);
752                                         ret = __run_svc_with_pkgname(APP_SELECTOR, b, request_code, cbfunc, data);
753                                         goto end;
754                                 }
755                         }
756                         for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
757                                 list_item = (char *)iter->data;
758                                 g_free(list_item);
759                         }
760                         g_slist_free(pkg_list);
761                         pkg_list = NULL;
762                 }  else {
763                         ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
764                         free(pkgname);
765                         goto end;
766                 }
767         }
768
769         /*scheme*/
770         pkgname = _svc_db_get_app(info.op, info.origin_mime, info.scheme, uid);
771
772         if(pkgname==NULL){
773                 __get_list_with_condition_mime_extened(info.op, info.scheme,
774                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
775
776                 __get_list_with_condition_mime_extened(info.op, "*",
777                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
778
779                 if(info.category) {
780                         __get_list_with_category(info.category, &pkg_list, uid);
781                 }
782
783                 __get_list_with_submode(info.win_id, &pkg_list, uid);
784
785                 pkg_count = g_slist_length(pkg_list);
786                 _D("pkg_count : %d", pkg_count);
787
788                 if(pkg_count == 1){
789                         pkgname = (char *)pkg_list->data;
790                         if(pkgname != NULL){
791                                 ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
792                         }
793                 } else if(pkg_count < 1) {
794                         __free_resolve_info_data(&info);
795                         return APPSVC_RET_ENOMATCH;
796                 } else {
797                         bundle_add(b, APP_SVC_K_URI_R_INFO, info.scheme);
798                         ret = __run_svc_with_pkgname(APP_SELECTOR, b, request_code, cbfunc, data);
799                 }
800
801                 for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
802                         list_item = (char *)iter->data;
803                         g_free(list_item);
804                 }
805                 g_slist_free(pkg_list); 
806         } else {
807                 ret = __run_svc_with_pkgname(pkgname, b, request_code, cbfunc, data);
808                 free(pkgname);
809         }
810
811 end:
812         __free_resolve_info_data(&info);
813
814         return ret;
815 }
816
817
818 SLPAPI int appsvc_get_list(bundle *b, appsvc_info_iter_fn iter_fn, void *data)
819 {
820         //using default user to allow app-svc API usage  for deamon.
821         //App-svc run get list leads to app launch that could require a graphical session.
822         return appsvc_usr_get_list(b, iter_fn, data, tzplatform_getuid(TZ_SYS_DEFAULT_USER));
823 }
824
825 SLPAPI int appsvc_usr_get_list(bundle *b, appsvc_info_iter_fn iter_fn, void *data, uid_t uid)
826 {
827         appsvc_resolve_info_t info;
828         char *pkgname = NULL;
829         int pkg_count;
830         int ret = -1;
831
832         GSList *pkg_list = NULL;
833         GSList *iter = NULL;
834
835         if(b == NULL){
836                 _E("bundle for appsvc_run_service is NULL");
837                 return APPSVC_RET_EINVAL;
838         }
839         
840         if (iter_fn == NULL){
841                 _E("iter_fn for appsvc_run_service is NULL");
842                 return APPSVC_RET_EINVAL;
843         }
844         
845         /* parse bundle */
846         memset(&info, 0, sizeof(appsvc_resolve_info_t));
847         ret = __get_resolve_info(b,&info);
848         if(ret < 0)
849                 return ret;
850         
851         _D("operation - %s / scheme - %s / mime - %s\n", info.op, info.scheme, info.mime);
852
853         __get_list_with_condition_mime_extened_with_collation(info.op, info.uri,
854                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
855
856         if(info.uri_r_info) {
857                 __get_list_with_condition_mime_extened(info.op, info.uri_r_info, 
858                         info.mime, info.m_type, info.s_type, &pkg_list, uid);
859         }
860         
861         __get_list_with_condition_mime_extened(info.op, info.scheme, 
862                 info.mime, info.m_type, info.s_type, &pkg_list, uid);
863
864         if(info.category) {
865                 __get_list_with_category(info.category, &pkg_list, uid);
866         }
867
868         __get_list_with_submode(info.win_id, &pkg_list, uid);
869
870         pkg_count = g_slist_length(pkg_list);
871         if (pkg_count == 0) {
872                 _E("Cannot find associated application");
873                 return APPSVC_RET_ENOMATCH;
874         }
875
876         for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
877                 pkgname = iter->data;
878                 _D("PKGNAME : %s\n", pkgname);
879                 if( iter_fn(pkgname,data) != 0)
880                         break;
881                 g_free(pkgname);
882         }
883
884         g_slist_free(pkg_list);
885         __free_resolve_info_data(&info);
886
887         return APPSVC_RET_OK;   
888 }
889
890 SLPAPI const char *appsvc_get_operation(bundle *b)
891 {
892         return bundle_get_val(b, APP_SVC_K_OPERATION);
893 }
894
895 SLPAPI const char *appsvc_get_uri(bundle *b)
896 {
897         return bundle_get_val(b, APP_SVC_K_URI);
898 }
899
900 SLPAPI const char *appsvc_get_mime(bundle *b)
901 {
902         return bundle_get_val(b, APP_SVC_K_MIME);
903 }
904
905 SLPAPI const char *appsvc_get_data(bundle *b, const char *key)
906 {
907         return bundle_get_val(b, key);
908 }
909
910 SLPAPI const char **appsvc_get_data_array(bundle *b, const char *key, int *len)
911 {
912         return bundle_get_str_array(b, key, len);
913 }
914
915 SLPAPI const char *appsvc_get_pkgname(bundle *b)
916 {
917         return bundle_get_val(b, APP_SVC_K_PKG_NAME);
918 }
919
920 SLPAPI const char *appsvc_get_appid(bundle *b)
921 {
922         return bundle_get_val(b, APP_SVC_K_PKG_NAME);
923 }
924
925 SLPAPI const char *appsvc_get_category(bundle *b)
926 {
927         return bundle_get_val(b, APP_SVC_K_CATEGORY);
928 }
929
930 SLPAPI const char *appsvc_get_launch_mode(bundle *b)
931 {
932         return bundle_get_val(b, APP_SVC_K_LAUNCH_MODE);
933 }
934
935 SLPAPI int appsvc_create_result_bundle(bundle *inb, bundle **outb)
936 {
937         int ret = -1;
938
939         if(inb == NULL || outb == NULL) {
940                 _E("bundle is NULL");
941                 return APPSVC_RET_EINVAL;
942         }
943         
944         ret = aul_create_result_bundle(inb, outb);
945
946         /* add additional bundle */
947         /*      bundle_add(outb, " ", " ");  */
948
949         if(ret == AUL_R_OK)
950                 ret = APPSVC_RET_OK;
951         else if(ret == AUL_R_EINVAL)
952                 ret = APPSVC_RET_EINVAL;
953         else
954                 ret = APPSVC_RET_ERROR;
955
956         return ret;
957 }
958
959 SLPAPI int appsvc_send_result(bundle *b, appsvc_result_val result)
960 {
961         int ret;
962         char tmp[MAX_LOCAL_BUFSZ];
963         
964         if(b == NULL){
965                 _E("appsvc_send_result is NULL");
966                 return APPSVC_RET_EINVAL;
967         }
968
969         if(result != APPSVC_RES_OK && result != APPSVC_RES_NOT_OK){
970                 _E("invalid result %d", (int)result);
971                 return APPSVC_RET_EINVAL;
972         }
973
974         /* add result_code to bundle */
975         snprintf(tmp,MAX_LOCAL_BUFSZ,"%d", (int)result);
976         ret = __set_bundle(b, APP_SVC_K_RES_VAL, tmp);
977         if(ret < 0)
978                 return APPSVC_RET_ERROR;
979
980         ret = aul_send_service_result(b);
981
982         /* remove result_code from bundle */
983         bundle_del(b, APP_SVC_K_RES_VAL);
984
985         return ret;
986
987
988 SLPAPI int appsvc_set_defapp(const char *op, const char *mime_type, const char *uri,
989                                         const char *defapp, uid_t uid)
990 {
991         int ret;
992
993         if(op == NULL || defapp == NULL)
994                 return APPSVC_RET_EINVAL;
995
996         ret = _svc_db_add_app(op, mime_type, uri, defapp, uid);
997
998         if(ret < 0)
999                 return APPSVC_RET_ERROR;
1000         
1001         return APPSVC_RET_OK;
1002 }
1003
1004 SLPAPI int appsvc_unset_defapp(const char *defapp, uid_t uid)
1005 {
1006         int ret;
1007
1008         if(defapp == NULL)
1009                 return APPSVC_RET_EINVAL;
1010
1011         ret = _svc_db_delete_with_pkgname(defapp, uid);
1012
1013         if(ret < 0) 
1014                 return APPSVC_RET_ERROR;
1015         
1016         return APPSVC_RET_OK;
1017 }
1018
1019 SLPAPI int appsvc_is_defapp(const char *pkg_name, uid_t uid)
1020 {
1021         return _svc_db_is_defapp(pkg_name, uid);
1022 }
1023
1024 SLPAPI int appsvc_data_is_array(bundle *b, const char *key)
1025 {
1026         int type;
1027         type = bundle_get_type(b, key);
1028
1029         if(type <= 0)
1030                 return 0;
1031
1032         if(type & BUNDLE_TYPE_ARRAY) 
1033                 return 1;
1034         return 0;
1035 }
1036
1037 typedef struct _appsvc_transient_cb_info_t{
1038         appsvc_host_res_fn cb_func;
1039
1040 #ifndef WAYLAND
1041         Ecore_X_Window win_id;
1042 #endif
1043
1044         void *data;
1045 }appsvc_transient_cb_info_t;
1046
1047 static Eina_Bool __transient_cb(void *data, int type, void *event)
1048 {
1049 #ifndef WAYLAND
1050         Ecore_X_Event_Window_Hide *ev;
1051         appsvc_transient_cb_info_t*  cb_info;
1052
1053         ev = event;
1054         cb_info = (appsvc_transient_cb_info_t*) data;
1055
1056         if(ev->win == cb_info->win_id) {
1057                 cb_info->cb_func(cb_info->data);
1058                 ecore_main_loop_quit();
1059         }
1060 #endif
1061         return ECORE_CALLBACK_RENEW;
1062 }
1063
1064 int __aul_subapp_cb(void *data)
1065 {
1066         appsvc_transient_cb_info_t*  cb_info;
1067
1068         cb_info = (appsvc_transient_cb_info_t*) data;
1069
1070         cb_info->cb_func(cb_info->data);
1071         ecore_main_loop_quit();
1072
1073         return 0;
1074 }
1075
1076 #ifndef WAYLAND
1077 SLPAPI int appsvc_allow_transient_app(bundle *b, Ecore_X_Window id)
1078 {
1079         char win_id[MAX_LOCAL_BUFSZ];
1080
1081         snprintf(win_id, MAX_LOCAL_BUFSZ, "%d", id);
1082
1083         if(b == NULL){
1084                 _E("bundle for appsvc_allow_transient_app is NULL");
1085                 return APPSVC_RET_EINVAL;
1086         }
1087
1088         return __set_bundle(b, APP_SVC_K_WIN_ID, win_id);
1089 }
1090 #else
1091 SLPAPI int appsvc_allow_transient_app(bundle *b, unsigned int id)
1092 {
1093         return 0;
1094 }
1095 #endif
1096
1097 #ifndef WAYLAND
1098 SLPAPI int appsvc_request_transient_app(bundle *b, Ecore_X_Window callee_id, appsvc_host_res_fn cbfunc, void *data)
1099 {
1100         char *caller = NULL;
1101         Ecore_X_Window caller_id;
1102
1103         caller = bundle_get_val(b, APP_SVC_K_WIN_ID);
1104         if(caller == NULL)
1105                 return APPSVC_RET_ERROR;
1106
1107         caller_id = atoi(caller);
1108
1109         ecore_x_icccm_transient_for_set(callee_id, caller_id);
1110
1111         ecore_x_window_client_manage(caller_id);
1112
1113         appsvc_transient_cb_info_t* info;
1114
1115         info = (appsvc_transient_cb_info_t*)calloc(1, sizeof(appsvc_transient_cb_info_t));
1116         if(info == NULL)
1117                 return APPSVC_RET_ERROR;
1118
1119         info->win_id = caller_id;
1120         info->cb_func = cbfunc;
1121         info->data = data;
1122
1123         ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, __transient_cb, info);
1124         aul_set_subapp(__aul_subapp_cb, info);
1125
1126         return 0;
1127 }
1128 #else
1129 SLPAPI int appsvc_request_transient_app(bundle *b, unsigned int callee_id, appsvc_host_res_fn cbfunc, void *data)
1130 {
1131         return 0;
1132 }
1133 #endif
1134
1135 SLPAPI int appsvc_subapp_terminate_request_pid(int pid)
1136 {
1137         int cpid = getpid();
1138         int lcnt;
1139         int *lpids = NULL;
1140         int i;
1141
1142         aul_app_group_get_leader_pids(&lcnt, &lpids);
1143         for (i = 0; i < lcnt; i++) {
1144                 if (lpids[i] == cpid) {
1145                         int cnt;
1146                         int *pids = NULL;
1147
1148                         aul_app_group_get_group_pids(cpid, &cnt, &pids);
1149
1150                         if (cnt == 0) {
1151                                 free(lpids);
1152                                 return aul_subapp_terminate_request_pid(pid);
1153                         }
1154
1155                         if (pids != NULL)
1156                                 free(pids);
1157                         break;
1158                 }
1159         }
1160
1161         if (lpids != NULL)
1162                 free(lpids);
1163
1164         return aul_app_group_clear_top();
1165 }
1166
1167 SLPAPI int aul_svc_subscribe_launch_result(bundle *b, const char *result)
1168 {
1169         if (b == NULL) {
1170                 _E("bundle for aul_svc_subscribe_launch_result is NULL");
1171                 return APPSVC_RET_EINVAL;
1172         }
1173
1174         return __set_bundle(b, result, "1");
1175 }