Fix type
[platform/core/appfw/aul-1.git] / src / service.c
1 /*
2  * Copyright (c) 2015 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 #define _GNU_SOURCE
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <uuid.h>
24 #include <bundle.h>
25 #include <bundle_internal.h>
26 #include <glib.h>
27 #include <string.h>
28 #include <pthread.h>
29 #include <dlfcn.h>
30 #include <iniparser.h>
31 #include <pkgmgr-info.h>
32
33 #include "aul.h"
34 #include "aul_api.h"
35 #include "aul_svc.h"
36 #include "aul_sock.h"
37 #include "aul_svc_db.h"
38 #include "aul_util.h"
39 #include "aul_svc_priv_key.h"
40 #include "launch.h"
41 #include "aul_svc_internal.h"
42 #include "aul_app_group.h"
43
44 #define MAX_CHECKSUM_BUF        2048
45 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
46 #define FREE_AND_NULL(x) do {   \
47         if (x) {                \
48                 free(x);        \
49                 x = NULL;       \
50         }                       \
51 } while (0)
52
53 /* callback handling */
54 typedef struct _aul_svc_cb_info_t {
55         int request_code;
56         aul_svc_res_fn cb_func;
57         aul_svc_err_cb err_cb;
58         void *data;
59 } aul_svc_cb_info_t;
60
61 typedef struct _aul_svc_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 } aul_svc_resolve_info_t;
76
77 typedef struct _aul_svc_transient_cb_info_t {
78         aul_svc_host_res_fn cb_func;
79         void *data;
80 } aul_svc_transient_cb_info_t;
81
82 pthread_mutex_t iniparser_lock = PTHREAD_MUTEX_INITIALIZER;
83 GSList *tmp_list;
84
85 static aul_svc_cb_info_t *__create_rescb(int request_code,
86                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb, void *data);
87 static void __remove_rescb(aul_svc_cb_info_t *info);
88 static int __set_bundle(bundle *b, const char *key, const char *value);
89 static void __aul_cb(bundle *b, int is_cancel, void *data);
90 static int __run_svc_with_pkgname(char *pkgname, bundle *b, int request_code,
91                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb, void *data,
92                 uid_t uid, bool sync);
93 static int __get_resolve_info(bundle *b, aul_svc_resolve_info_t *info);
94 static int __free_resolve_info_data(aul_svc_resolve_info_t *info);
95
96 static char *white_list[] = {
97         APP_SELECTOR,
98         SHARE_PANEL,
99         NULL
100 };
101
102 static bool __is_special_app(const char *appid)
103 {
104         const char *id;
105         int i = 0;
106
107         if (appid == NULL)
108                 return false;
109
110         while ((id = white_list[i]) != NULL) {
111                 if (strcmp(id, appid) == 0)
112                         return true;
113                 i++;
114         }
115         return false;
116 }
117
118 static bool __is_special_operation(bundle *b)
119 {
120         const char *operation;
121         const char *white_operations[] = {
122                 "http://tizen.org/appcontrol/operation/guide_privacy_setting",
123                 NULL
124         };
125         int i;
126
127         operation = aul_svc_get_operation(b);
128         if (!operation)
129                 return false;
130
131         for (i = 0; white_operations[i]; ++i) {
132                 if (!strcmp(operation, white_operations[i]))
133                         return true;
134         }
135
136         return false;
137 }
138
139 static aul_svc_cb_info_t *__create_rescb(int request_code,
140                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb, void *data)
141 {
142         aul_svc_cb_info_t* info;
143
144         info = calloc(1, sizeof(aul_svc_cb_info_t));
145         if (info == NULL) {
146                 _E("Out of memory");
147                 return NULL;
148         }
149
150         info->request_code = request_code;
151         info->cb_func = cbfunc;
152         info->err_cb = err_cb;
153         info->data = data;
154
155         return info;
156 }
157
158 static void __remove_rescb(aul_svc_cb_info_t *info)
159 {
160         if (info)
161                 free(info);
162 }
163
164 static int __set_bundle(bundle *b, const char *key, const char *value)
165 {
166         const char *val = NULL;
167
168         val = bundle_get_val(b, key);
169         if (val) {
170                 if (bundle_del(b, key) != 0)
171                         return AUL_SVC_RET_ERROR;
172         }
173
174         if (!value)
175                 return AUL_SVC_RET_EINVAL;
176
177         if (bundle_add(b, key, value) != 0)
178                 return AUL_SVC_RET_ERROR;
179
180         _D("__set_bundle");
181
182         return AUL_SVC_RET_OK;
183 }
184
185 static int __set_bundle_array(bundle *b, const char *key,
186                                 const char **value, int len)
187 {
188
189         int type;
190         type = aul_svc_data_is_array(b, key);
191
192         if (type == 1) {
193                 if (bundle_del(b, key) != 0)
194                         return AUL_SVC_RET_ERROR;
195         }
196
197         if (!value)
198                 return AUL_SVC_RET_EINVAL;
199
200         if (bundle_add_str_array(b, key, value, len) != 0)
201                 return AUL_SVC_RET_ERROR;
202
203         _D("__set_bundle_array");
204
205         return AUL_SVC_RET_OK;
206 }
207
208 static void __aul_cb(bundle *b, int is_cancel, void *data)
209 {
210         const char *val = NULL;
211         aul_svc_cb_info_t*  cb_info;
212         int res;
213
214         if (is_cancel)
215                 res = AUL_SVC_RES_CANCEL;
216         else {
217                 /* get result_code from bundle */
218                 val = bundle_get_val(b, AUL_SVC_K_RES_VAL);
219                 res = (val == NULL) ? AUL_SVC_RES_NOT_OK : atoi(val);
220         }
221
222         /* remove result_code from bundle */
223         bundle_del(b, AUL_SVC_K_RES_VAL);
224
225         /* find corresponding callback */
226         cb_info = (aul_svc_cb_info_t*)data;
227
228         if (cb_info->cb_func) {
229                 cb_info->cb_func(b, cb_info->request_code,
230                                 (aul_svc_result_val)res, cb_info->data);
231                 cb_info->cb_func = NULL;
232         }
233
234         if (cb_info->err_cb)
235                 return;
236
237         __remove_rescb(cb_info);
238 }
239
240 static int __error_convert(int res)
241 {
242         switch (res) {
243         case AUL_R_EILLACC:
244                 return AUL_SVC_RET_EILLACC;
245         case AUL_R_EINVAL:
246                 return AUL_SVC_RET_EINVAL;
247         case AUL_R_ETERMINATING:
248                 return AUL_SVC_RET_ETERMINATING;
249         case AUL_R_EREJECTED:
250                 return AUL_SVC_RET_EREJECTED;
251         case AUL_R_ENOAPP:
252                 return AUL_SVC_RET_ENOMATCH;
253         default:
254                 return AUL_SVC_RET_ELAUNCH;
255         }
256 }
257
258 static void __aul_error_cb(int err, void *data)
259 {
260         aul_svc_cb_info_t *cb_info = (aul_svc_cb_info_t *)data;
261
262         if (!cb_info) {
263                 _E("Critical error!");
264                 return;
265         }
266
267         if (err < 0)
268                 err = __error_convert(err);
269
270         if (cb_info->err_cb) {
271                 cb_info->err_cb(cb_info->request_code, err, cb_info->data);
272                 cb_info->err_cb = NULL;
273         }
274
275         if (cb_info->cb_func)
276                 return;
277
278         __remove_rescb(cb_info);
279 }
280
281 static void __set_instance_id(bundle *b, const char *appid)
282 {
283         const char *comp_id;
284         char buf[1024];
285         char uuid[37];
286         uuid_t u;
287
288         uuid_generate(u);
289         uuid_unparse(u, uuid);
290
291         comp_id = bundle_get_val(b, AUL_K_COMPONENT_ID);
292         if (comp_id)
293                 snprintf(buf, sizeof(buf), "%s:%s:%s", uuid, appid, comp_id);
294         else
295                 snprintf(buf, sizeof(buf), "%s:%s", uuid, appid);
296
297         bundle_add(b, AUL_K_INSTANCE_ID, buf);
298 }
299
300 static void __verify_request(bundle *b, char **appid)
301 {
302         const char *launch_mode;
303         int ret;
304
305         ret = bundle_get_type(b, AUL_SVC_K_SELECTOR_EXTRA_LIST);
306         if (ret != BUNDLE_TYPE_NONE) {
307                 if (!aul_svc_get_pkgname(b))
308                         *appid = APP_SELECTOR;
309         }
310
311         if (bundle_get_val(b, AUL_K_FORCE_LAUNCH_APP_SELECTOR))
312                 *appid = APP_SELECTOR;
313
314         if (__is_special_app(*appid) || __is_special_operation(b)) {
315                 bundle_del(b, AUL_SVC_K_CAN_BE_LEADER);
316                 bundle_add_str(b, AUL_SVC_K_CAN_BE_LEADER, "true");
317                 bundle_del(b, AUL_SVC_K_REROUTE);
318                 bundle_add_str(b, AUL_SVC_K_REROUTE, "true");
319                 bundle_del(b, AUL_SVC_K_RECYCLE);
320                 bundle_add_str(b, AUL_SVC_K_RECYCLE, "true");
321         }
322
323         launch_mode = aul_svc_get_launch_mode(b);
324         if (launch_mode && !strcmp(launch_mode, "group")) {
325                 ret = bundle_get_type(b, AUL_K_INSTANCE_ID);
326                 if (ret == BUNDLE_TYPE_NONE)
327                         __set_instance_id(b, *appid);
328         }
329 }
330
331 static int __run_svc_with_pkgname(char *pkgname, bundle *b, int request_code,
332                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
333                 void *data, uid_t uid, bool sync)
334 {
335         aul_svc_cb_info_t *cb_info = NULL;
336         int ret = -1;
337
338         __verify_request(b, &pkgname);
339
340         if (cbfunc || err_cb) {
341                 SECURE_LOGD("pkg_name : %s - with result", pkgname);
342
343                 cb_info = __create_rescb(request_code, cbfunc, err_cb, data);
344                 if (sync) {
345                         ret = aul_launch_app_with_result_for_uid(pkgname, b,
346                                         __aul_cb, cb_info, uid);
347                 } else {
348                         if (err_cb) {
349                                 ret = aul_send_launch_request_for_uid(pkgname,
350                                                 b, uid,
351                                                 cbfunc ? __aul_cb : NULL,
352                                                 __aul_error_cb,
353                                                 cb_info);
354                         } else {
355                                 ret = aul_launch_app_with_result_async_for_uid(
356                                                 pkgname, b, __aul_cb,
357                                                 cb_info, uid);
358                         }
359                 }
360         } else {
361                 SECURE_LOGD("pkg_name : %s - no result", pkgname);
362
363 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
364                 const char* data = bundle_get_val(b, AUL_SVC_K_MULTI_INSTANCE);
365                 if (data)
366                         SECURE_LOGD("multi_instance value = %s", data);
367
368                 if (data && strncmp(data, "TRUE", strlen("TRUE")) == 0) {
369                         if (sync) {
370                                 ret = aul_launch_app_for_multi_instance(pkgname,
371                                                 b);
372                         } else {
373                                 ret = aul_launch_app_for_multi_instance_async(
374                                                 pkgname, b);
375                         }
376                 } else {
377                         if (sync)
378                                 ret = aul_launch_app(pkgname, b);
379                         else
380                                 ret = aul_launch_app_async(pkgname, b, uid);
381                 }
382 #else
383                 if (sync)
384                         ret = aul_launch_app_for_uid(pkgname, b, uid);
385                 else
386                         ret = aul_launch_app_async_for_uid(pkgname, b, uid);
387 #endif
388         }
389
390         if (ret < 0) {
391                 if (cb_info)
392                         __remove_rescb(cb_info);
393                 ret = __error_convert(ret);
394         }
395
396         return ret;
397 }
398
399 static int __get_resolve_info(bundle *b, aul_svc_resolve_info_t *info)
400 {
401         char *tmp = NULL;
402         char *saveptr = NULL;
403         char *strtok_buf = NULL;
404         int ret = -1;
405
406         info->op = (char *)aul_svc_get_operation(b);
407         info->uri = (char *)aul_svc_get_uri(b);
408
409         if ((info->uri) && (strcmp(info->uri, "") == 0)) {
410                 _E("Uri is empty");
411                 return AUL_SVC_RET_EINVAL;
412         }
413
414         info->origin_mime = info->mime = (char *)aul_svc_get_mime(b);
415         info->pkgname = (char *)aul_svc_get_pkgname(b);
416         info->category = (char *)aul_svc_get_category(b);
417         info->win_id = (char *)bundle_get_val(b, AUL_SVC_K_WIN_ID);
418
419         SECURE_LOGD("getting resolve info for: operation - %s / uri - %s / mime - %s",
420                         info->op, info->uri, info->mime);
421
422         if (info->uri) {
423                 if (strncmp(info->uri, "/", 1) == 0) {
424                         if (!info->mime) {
425                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
426                                 if (info->mime == NULL) {
427                                         _E("out of memory");
428                                         return AUL_SVC_RET_ERROR;
429                                 }
430
431                                 ret = aul_get_mime_from_file(info->uri, info->mime, MAX_MIME_STR_SIZE);
432                                 info->mime_set = 1;
433                         }
434                         info->uri = NULL;
435                 } else if (strncmp(info->uri, "file:///", 8) == 0) {
436                         if (!info->mime) {
437                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
438                                 if (info->mime == NULL) {
439                                         _E("out of memory");
440                                         return AUL_SVC_RET_ERROR;
441                                 }
442
443                                 ret = aul_get_mime_from_file(&info->uri[7], info->mime, MAX_MIME_STR_SIZE);
444                                 info->mime_set = 1;
445                         }
446                 } else if (strncmp(info->uri, "file:/", 6) == 0) {
447                         if (!info->mime) {
448                                 info->origin_mime = info->mime = malloc(MAX_MIME_STR_SIZE);
449                                 if (info->mime == NULL) {
450                                         _E("out of memory");
451                                         return AUL_SVC_RET_ERROR;
452                                 }
453
454                                 ret = aul_get_mime_from_file(&info->uri[5], info->mime, MAX_MIME_STR_SIZE);
455                                 info->mime_set = 1;
456                         }
457                 }
458
459                 if (info->mime_set == 1 && ret < 0) {
460                         _E("aul_get_mime_from_file : %d", ret);
461                         free(info->mime);
462                         info->origin_mime = info->mime = NULL;
463                         info->mime_set = 0;
464                 }
465         }
466
467         if (info->uri) {
468                 GRegex *regex;
469                 GMatchInfo *match_info;
470                 GError *error = NULL;
471
472                 regex = g_regex_new("^(([^:/?#]+):)?(//([^/?#]*))?", 0, 0, &error);
473                 if (g_regex_match(regex, info->uri, 0, &match_info) == FALSE) {
474                         g_regex_unref(regex);
475                         return AUL_SVC_RET_EINVAL;
476                 }
477
478                 info->scheme = g_match_info_fetch(match_info, 2);
479                 info->host = g_match_info_fetch(match_info, 4);
480
481                 if (info->scheme && info->host) {
482                         info->uri_r_info = malloc(MAX_SCHEME_STR_SIZE + MAX_HOST_STR_SIZE + 2);
483                         if (info->uri_r_info == NULL) {
484                                 _E("out of memory");
485                                 g_match_info_free(match_info);
486                                 g_regex_unref(regex);
487                                 return AUL_SVC_RET_ERROR;
488                         }
489
490                         snprintf(info->uri_r_info, MAX_SCHEME_STR_SIZE + MAX_HOST_STR_SIZE + 1,
491                                                 "%s://%s", info->scheme, info->host);
492                 }
493
494                 g_match_info_free(match_info);
495                 g_regex_unref(regex);
496
497         } else {
498                 info->scheme = strdup("NULL");
499         }
500
501         if (!info->mime) {
502                 info->mime = strdup("NULL");
503                 return 0;
504         }
505
506         info->m_type = calloc(1, MAX_LOCAL_BUFSZ);
507         if (info->m_type == NULL) {
508                 _E("ouf of memory");
509                 return AUL_SVC_RET_ERROR;
510         }
511
512         info->s_type = calloc(1, MAX_LOCAL_BUFSZ);
513         if (info->s_type == NULL) {
514                 _E("out of memory");
515                 free(info->m_type);
516                 return AUL_SVC_RET_ERROR;
517         }
518
519         tmp = strdup(info->mime);
520         if (tmp == NULL) {
521                 _E("out of memory");
522                 free(info->s_type);
523                 free(info->m_type);
524                 return AUL_SVC_RET_ERROR;
525         }
526
527         strtok_buf = strtok_r(tmp, "/", &saveptr);
528         if (strtok_buf)
529                 strncpy(info->m_type, strtok_buf, MAX_LOCAL_BUFSZ - 1);
530         strtok_buf = strtok_r(NULL, "/", &saveptr);
531         if (strtok_buf)
532                 strncpy(info->s_type, strtok_buf, MAX_LOCAL_BUFSZ - 1);
533         free(tmp);
534
535         if (strncmp(info->m_type, "*", 1) == 0)
536                 strncpy(info->m_type, "%", MAX_LOCAL_BUFSZ - 1);
537         if (strncmp(info->s_type, "*", 1) == 0)
538                 strncpy(info->s_type, "%", MAX_LOCAL_BUFSZ - 1);
539
540         info->mime = malloc(MAX_MIME_STR_SIZE);
541         if (info->mime == NULL) {
542                 _E("out of memory");
543                 free(info->s_type);
544                 free(info->m_type);
545                 return AUL_SVC_RET_ERROR;
546         }
547
548         snprintf(info->mime, MAX_MIME_STR_SIZE - 1,
549                         "%s/%s", info->m_type, info->s_type);
550
551         return 0;
552 }
553
554 static int __free_resolve_info_data(aul_svc_resolve_info_t *info)
555 {
556         if (info->mime)
557                 free(info->mime);
558         if (info->scheme)
559                 free(info->scheme);
560         if (info->host)
561                 free(info->host);
562         if (info->m_type)
563                 free(info->m_type);
564         if (info->s_type)
565                 free(info->s_type);
566         if (info->uri_r_info)
567                 free(info->uri_r_info);
568         if (info->mime_set)
569                 free(info->origin_mime);
570
571         return 0;
572 }
573
574 static char* __get_alias_appid(char *appid)
575 {
576         char *alias_id = NULL;
577         const char *val = NULL;
578         char key_string[MAX_PACKAGE_STR_SIZE + 5];
579         dictionary *dic;
580
581         dic = iniparser_load("/usr/share/appsvc/alias.ini");
582
583         if (dic == NULL)
584                 return NULL;
585
586         snprintf(key_string, sizeof(key_string), "Alias:%s", appid);
587         pthread_mutex_lock(&iniparser_lock);
588         val = iniparser_getstring(dic, key_string, NULL);
589         pthread_mutex_unlock(&iniparser_lock);
590
591         SECURE_LOGD("alias_id : %s", val);
592
593         if (val != NULL) {
594                 alias_id = malloc(MAX_PACKAGE_STR_SIZE);
595                 if (alias_id == NULL) {
596                         _E("out of memory");
597                         iniparser_freedict(dic);
598                         return NULL;
599                 }
600
601                 strncpy(alias_id, val, MAX_PACKAGE_STR_SIZE - 1);
602         }
603
604         iniparser_freedict(dic);
605
606         return alias_id;
607 }
608
609 static char* __make_query(char *query, char *op, char *uri,
610                         char *mime, char *m_type, char *s_type)
611 {
612         char tmp[MAX_MIME_STR_SIZE] = { 0, };
613
614         query = _svc_db_query_builder_add(query, op, uri, mime, false);
615         if ((mime && strncmp(mime, "NULL", 4) != 0) &&
616                         (s_type && strncmp(s_type, "%", 1) != 0)) {
617                 snprintf(tmp, MAX_MIME_STR_SIZE - 1, "%s/*", m_type);
618                 query = _svc_db_query_builder_add(query, op, uri, tmp, false);
619         }
620
621         if ((mime && strncmp(mime, "NULL", 4) != 0) &&
622                         (m_type && strncmp(m_type, "%", 1) != 0)) {
623                 snprintf(tmp, MAX_MIME_STR_SIZE - 1, "*/*");
624                 query = _svc_db_query_builder_add(query, op, uri, tmp, false);
625         }
626
627         return query;
628 }
629
630 static char* __make_query_with_collation(char *op, char *uri, char *mime, char *m_type, char *s_type)
631 {
632         char tmp[MAX_MIME_STR_SIZE];
633         char *query = NULL;
634
635         query = _svc_db_query_builder_add(query, op, uri, mime, true);
636
637         if (mime && (strncmp(mime, "NULL", 4) != 0) &&
638                         s_type && (strncmp(s_type, "%", 1) != 0)) {
639                 snprintf(tmp, MAX_MIME_STR_SIZE - 1, "%s/*", m_type);
640                 query = _svc_db_query_builder_add(query, op, uri, tmp, true);
641         }
642         if (mime && (strncmp(mime, "NULL", 4) != 0) &&
643                         m_type && (strncmp(m_type, "%", 1) != 0)) {
644                 snprintf(tmp, MAX_MIME_STR_SIZE - 1, "*/*");
645                 query = _svc_db_query_builder_add(query, op, uri, tmp, true);
646         }
647
648         query = _svc_db_query_builder_in("ac.app_control collate appsvc_collation ", query);
649
650         return query;
651 }
652
653
654 static int __app_list_cb(pkgmgrinfo_appinfo_h handle, void *user_data)
655 {
656         char *appid = NULL;
657         GSList **app_list = (GSList **)user_data;
658         char *str = NULL;
659         GSList *iter = NULL;
660
661         pkgmgrinfo_appinfo_get_appid(handle, &str);
662         _D("Matching application is %s", str);
663
664         for (iter = tmp_list; iter != NULL; iter = g_slist_next(iter)) {
665                 if (strncmp(str, (char *)iter->data, MAX_PACKAGE_STR_SIZE - 1) == 0) {
666                         appid = strdup(str);
667                         *app_list = g_slist_append(*app_list, (void *)appid);
668                         _D("%s is added", appid);
669                 }
670         }
671
672         return 0;
673 }
674
675 static int __get_list_with_category(char *category, GSList **pkg_list, uid_t uid)
676 {
677         int ret;
678         pkgmgrinfo_appinfo_filter_h handle;
679         GSList *app_list = NULL;
680         GSList *iter = NULL;
681         char *list_item = NULL;
682
683         ret = pkgmgrinfo_appinfo_filter_create(&handle);
684         ret = pkgmgrinfo_appinfo_filter_add_string(handle,
685                                 PMINFO_APPINFO_PROP_APP_CATEGORY, category);
686
687         tmp_list = *pkg_list;
688         ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(handle,
689                                 __app_list_cb, &app_list, uid);
690         if (ret != PMINFO_R_OK) {
691                 pkgmgrinfo_appinfo_filter_destroy(handle);
692                 return -1;
693         }
694         pkgmgrinfo_appinfo_filter_destroy(handle);
695
696         for (iter = *pkg_list; iter != NULL; iter = g_slist_next(iter)) {
697                 list_item = (char *)iter->data;
698                 g_free(list_item);
699         }
700         g_slist_free(*pkg_list);
701
702         *pkg_list = app_list;
703
704         return 0;
705 }
706
707 static int __check_mainapp_mode(char *operation)
708 {
709         return 0;
710 }
711
712 static int __get_list_with_submode(char *operation, char *win_id,
713                                 GSList **pkg_list, uid_t uid)
714 {
715         int ret = 0;
716         int mainapp_mode = 0;
717
718         mainapp_mode = __check_mainapp_mode(operation);
719
720         SECURE_LOGD("mainapp_mode : %d", mainapp_mode);
721
722         ret = _svc_db_adjust_list_with_submode(mainapp_mode, win_id, pkg_list, uid);
723
724         if (ret < 0) {
725                 _E("error: %d", ret);
726                 return -1;
727         }
728
729         return 0;
730 }
731
732 static void __free_pkg_list(GSList *list)
733 {
734         char *list_item;
735         GSList *iter = NULL;
736
737         if (list == NULL)
738                 return;
739
740         for (iter = list; iter != NULL; iter = g_slist_next(iter)) {
741                 list_item = (char *)iter->data;
742                 g_free(list_item);
743         }
744         g_slist_free(list);
745 }
746
747 static gchar *__make_checksum(const char *op, const char *uri, const char *mime)
748 {
749         char buf[MAX_CHECKSUM_BUF];
750         gchar *checksum;
751
752         snprintf(buf, sizeof(buf), "%s:%s:%s", op, uri, mime);
753         checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5, buf, -1);
754
755         return checksum;
756 }
757
758 static char *__get_cache(const char *checksum, uid_t uid)
759 {
760         app_pkt_t *pkt = NULL;
761         int fd;
762         int ret;
763         bundle *b;
764         char buf[MAX_PID_STR_BUFSZ];
765         char *appid;
766
767         b = bundle_create();
768         if (b == NULL) {
769                 _E("out of memory");
770                 return NULL;
771         }
772
773         snprintf(buf, sizeof(buf), "%d", uid);
774         bundle_add(b, AUL_K_TARGET_UID, buf);
775         bundle_add(b, AUL_K_CHECKSUM, checksum);
776
777         fd = aul_sock_send_bundle(AUL_UTIL_PID, uid, APP_GET_APPID_FROM_CACHE,
778                         b, AUL_SOCK_ASYNC);
779         bundle_free(b);
780         if (fd <= 0)
781                 return NULL;
782
783         ret = aul_sock_recv_reply_pkt(fd, &pkt);
784         if (ret < 0)
785                 return NULL;
786
787         if (pkt->cmd == APP_GET_APPID_FROM_CACHE) {
788                 if (pkt->data[0] == 0) {
789                         free(pkt);
790                         return NULL;
791                 }
792                 appid = strdup((const char *)(pkt->data));
793                 free(pkt);
794                 return appid;
795         }
796         free(pkt);
797
798         return NULL;
799 }
800
801 static void __put_cache(const char *checksum, const char *appid, uid_t uid)
802 {
803         int ret;
804         bundle *b;
805         char buf[MAX_PID_STR_BUFSZ];
806
807         b = bundle_create();
808         if (!b) {
809                 _E("out of memory");
810                 return;
811         }
812
813         snprintf(buf, sizeof(buf), "%d", uid);
814         bundle_add(b, AUL_K_TARGET_UID, buf);
815         bundle_add(b, AUL_K_CHECKSUM, checksum);
816         bundle_add(b, AUL_K_APPID, appid);
817
818         ret = app_send_cmd_for_uid(AUL_UTIL_PID, uid, APP_SET_CACHE, b);
819
820         if (ret < 0)
821                 _E("Failed to set cache : %d", ret);
822
823         bundle_free(b);
824 }
825
826 static void __put_cache_with_info(const char *checksum, const char *info, uid_t uid)
827 {
828         char buf[PATH_MAX];
829
830         snprintf(buf, sizeof(buf), "@APP_SELECTOR %s", info);
831         __put_cache(checksum, buf, uid);
832 }
833
834 static void __invalidate_cache(uid_t uid)
835 {
836         int ret;
837         bundle *b;
838         char buf[MAX_PID_STR_BUFSZ];
839
840         b = bundle_create();
841         if (!b) {
842                 _E("out of memory");
843                 return;
844         }
845
846         snprintf(buf, sizeof(buf), "%d", uid);
847         bundle_add(b, AUL_K_TARGET_UID, buf);
848         ret = app_send_cmd_for_uid(AUL_UTIL_PID, uid, APP_INVALIDATE_CACHE, b);
849
850         if (ret < 0)
851                 _E("Failed to invalidate cache : %d", ret);
852
853         bundle_free(b);
854 }
855
856 API int aul_svc_set_operation(bundle *b, const char *operation)
857 {
858         if (b == NULL) {
859                 _E("bundle is NULL");
860                 return AUL_SVC_RET_EINVAL;
861         }
862
863         return __set_bundle(b, AUL_SVC_K_OPERATION, operation);
864 }
865
866 API int aul_svc_set_uri(bundle *b, const char *uri)
867 {
868         if (b == NULL) {
869                 _E("bundle is NULL");
870                 return AUL_SVC_RET_EINVAL;
871         }
872
873         return __set_bundle(b, AUL_SVC_K_URI, uri);
874 }
875
876 API int aul_svc_set_mime(bundle *b, const char *mime)
877 {
878         if (b == NULL) {
879                 _E("bundle is NULL");
880                 return AUL_SVC_RET_EINVAL;
881         }
882
883         return __set_bundle(b, AUL_SVC_K_MIME, mime);
884 }
885
886 API int aul_svc_add_data(bundle *b, const char *key, const char *val)
887 {
888         if (b == NULL || key == NULL)
889                 return AUL_SVC_RET_EINVAL;
890
891         /* check key for data */
892         /******************/
893
894         return __set_bundle(b, key, val);
895 }
896
897 API int aul_svc_add_data_array(bundle *b, const char *key,
898                                 const char **val_array, int len)
899 {
900         if (b == NULL || key == NULL)
901                 return AUL_SVC_RET_EINVAL;
902
903         /* check key for data */
904         /******************/
905
906         return __set_bundle_array(b, key, val_array, len);
907 }
908
909 API int aul_svc_set_pkgname(bundle *b, const char *pkg_name)
910 {
911         if (b == NULL) {
912                 _E("bundle is NULL");
913                 return AUL_SVC_RET_EINVAL;
914         }
915
916         return __set_bundle(b, AUL_SVC_K_PKG_NAME, pkg_name);
917 }
918
919 API int aul_svc_set_appid(bundle *b, const char *appid)
920 {
921         char *alias_id = NULL;
922         int ret;
923
924         if (b == NULL || appid == NULL) {
925                 _E("bundle is NULL");
926                 return AUL_SVC_RET_EINVAL;
927         }
928
929         alias_id = __get_alias_appid((char *)appid);
930         if (alias_id == NULL) {
931                 ret = __set_bundle(b, AUL_SVC_K_PKG_NAME, appid);
932         } else {
933                 ret = __set_bundle(b, AUL_SVC_K_PKG_NAME, alias_id);
934                 free(alias_id);
935                 alias_id = NULL;
936         }
937
938         return ret;
939 }
940
941 API int aul_svc_set_category(bundle *b, const char *category)
942 {
943         if (b == NULL) {
944                 _E("bundle is NULL");
945                 return AUL_SVC_RET_EINVAL;
946         }
947
948         return __set_bundle(b, AUL_SVC_K_CATEGORY, category);
949 }
950
951 API int aul_svc_set_launch_mode(bundle *b, const char *mode)
952 {
953         if (b == NULL) {
954                 _E("bundle is NULL");
955                 return AUL_SVC_RET_EINVAL;
956         }
957
958         return __set_bundle(b, AUL_SVC_K_LAUNCH_MODE, mode);
959 }
960
961 typedef struct resolution_info_s {
962         char *appid;
963         const char *uri_r_info;
964         GSList *list;
965         bundle *b;
966         uid_t uid;
967         aul_svc_resolve_info_t ri;
968         gchar *checksum;
969         char *cache;
970 } resolution_info_t;
971
972 typedef int (*resolution_handler)(resolution_info_t *info);
973
974 static int __resolution_pre(resolution_info_t *info)
975 {
976         aul_svc_resolve_info_t *ri = &info->ri;
977         int ret;
978         size_t n;
979
980         ret = __get_resolve_info(info->b, ri);
981         if (ret < 0)
982                 goto err;
983
984         SECURE_LOGD("op - %s / mime - %s / scheme - %s",
985                         ri->op, ri->origin_mime, ri->scheme);
986
987         info->checksum = __make_checksum(ri->op, ri->uri, ri->origin_mime);
988         info->cache = __get_cache(info->checksum, info->uid);
989         if (info->cache) {
990                 _D("Hit! %s / %s", info->checksum, info->cache);
991                 n = strlen("@APP_SELECTOR ");
992                 if (!strncmp("@APP_SELECTOR ", info->cache, n)) {
993                         bundle_add(info->b, AUL_SVC_K_URI_R_INFO,
994                                         &info->cache[n]);
995                         info->appid = strdup(APP_SELECTOR);
996                         if (info->appid == NULL) {
997                                 _E("Out of memory");
998                                 ret = AUL_SVC_RET_ERROR;
999                                 goto err;
1000                         }
1001                 } else if (!strcmp(info->cache, "^")) {
1002                         ret = AUL_SVC_RET_ENOMATCH;
1003                         goto err;
1004                 } else {
1005                         info->appid = info->cache;
1006                 }
1007
1008                 return AUL_SVC_RET_OK;
1009         }
1010
1011         return AUL_SVC_RET_OK;
1012
1013 err:
1014         if (info->cache) {
1015                 free(info->cache);
1016                 info->cache = NULL;
1017         }
1018
1019         if (info->checksum) {
1020                 g_free(info->checksum);
1021                 info->checksum = NULL;
1022         }
1023
1024         __free_resolve_info_data(ri);
1025
1026         return ret;
1027 }
1028
1029 static int __resolution_uri(resolution_info_t *info)
1030 {
1031         aul_svc_resolve_info_t *ri = &info->ri;
1032         char *id;
1033         char *query;
1034
1035         if (info->appid || info->list)
1036                 return AUL_SVC_RET_OK;
1037
1038         id = _svc_db_get_app(ri->op, ri->origin_mime, ri->uri, info->uid);
1039         if (id) {
1040                 info->appid = id;
1041                 return AUL_SVC_RET_OK;
1042         }
1043
1044         query = __make_query_with_collation(ri->op, ri->uri, ri->mime,
1045                         ri->m_type, ri->s_type);
1046         query = _svc_db_query_builder_build(query);
1047         _svc_db_exec_query(query, &info->list, info->uid);
1048         FREE_AND_NULL(query);
1049
1050         if (!info->list)
1051                 return AUL_SVC_RET_OK;
1052
1053         __free_pkg_list(info->list);
1054         info->list = NULL;
1055
1056         if (ri->uri_r_info) {
1057                 query = __make_query(query, ri->op, ri->uri_r_info,
1058                                 ri->mime, ri->m_type, ri->s_type);
1059         }
1060
1061         query = __make_query(query, ri->op, ri->scheme, ri->mime,
1062                         ri->m_type, ri->s_type);
1063         query = __make_query(query, ri->op, "*", ri->mime,
1064                         ri->m_type, ri->s_type);
1065         if ((ri->scheme && strcmp(ri->scheme, "file") == 0) &&
1066                         (ri->mime && strcmp(ri->mime, "NULL") != 0)) {
1067                 query = __make_query(query, ri->op, "NULL", ri->mime,
1068                                 ri->m_type, ri->s_type);
1069         }
1070         query = _svc_db_query_builder_build(query);
1071         _svc_db_exec_query(query, &info->list, info->uid);
1072         FREE_AND_NULL(query);
1073
1074         if (ri->category)
1075                 __get_list_with_category(ri->category, &info->list, info->uid);
1076         __get_list_with_submode(ri->op, ri->win_id, &info->list, info->uid);
1077
1078         if (g_slist_length(info->list) > 1)
1079                 info->uri_r_info = ri->uri;
1080
1081         return AUL_SVC_RET_OK;
1082 }
1083
1084 static int __resolution_scheme_and_host(resolution_info_t *info)
1085 {
1086         aul_svc_resolve_info_t *ri = &info->ri;
1087         char *id;
1088         char *query = NULL;
1089
1090         if (info->appid || info->list)
1091                 return AUL_SVC_RET_OK;
1092
1093         if (!ri->uri_r_info)
1094                 return AUL_SVC_RET_OK;
1095
1096         id = _svc_db_get_app(ri->op, ri->origin_mime, ri->uri_r_info,
1097                         info->uid);
1098         if (id) {
1099                 info->appid = id;
1100                 return AUL_SVC_RET_OK;
1101         }
1102
1103         query = __make_query(query, ri->op, ri->uri_r_info, ri->mime,
1104                         ri->m_type, ri->s_type);
1105         query = _svc_db_query_builder_build(query);
1106         _svc_db_exec_query(query, &info->list, info->uid);
1107         FREE_AND_NULL(query);
1108
1109         if (!info->list)
1110                 return AUL_SVC_RET_OK;
1111
1112         __free_pkg_list(info->list);
1113         info->list = NULL;
1114
1115         query = __make_query(query, ri->op, "*", ri->mime, ri->m_type,
1116                         ri->s_type);
1117         if ((ri->scheme && strcmp(ri->scheme, "file") == 0) &&
1118                                 (ri->mime && strcmp(ri->mime, "NULL") != 0)) {
1119                 query = __make_query(query, ri->op, "NULL", ri->mime,
1120                                 ri->m_type, ri->s_type);
1121         }
1122         query = _svc_db_query_builder_build(query);
1123         _svc_db_exec_query(query, &info->list, info->uid);
1124         FREE_AND_NULL(query);
1125
1126         if (ri->category)
1127                 __get_list_with_category(ri->category, &info->list, info->uid);
1128         __get_list_with_submode(ri->op, ri->win_id, &info->list, info->uid);
1129
1130         if (g_slist_length(info->list) > 1)
1131                 info->uri_r_info = ri->uri_r_info;
1132
1133         return AUL_SVC_RET_OK;
1134 }
1135
1136 static int __resolution_scheme(resolution_info_t *info)
1137 {
1138         aul_svc_resolve_info_t *ri = &info->ri;
1139         char *id;
1140         char *query = NULL;
1141
1142         if (info->appid || info->list)
1143                 return AUL_SVC_RET_OK;
1144
1145         id = _svc_db_get_app(ri->op, ri->origin_mime, ri->scheme, info->uid);
1146         if (id) {
1147                 info->appid = id;
1148                 return AUL_SVC_RET_OK;
1149         }
1150
1151         query = __make_query(query, ri->op, ri->scheme, ri->mime,
1152                         ri->m_type, ri->s_type);
1153         query = __make_query(query, ri->op, "*", ri->mime,
1154                         ri->m_type, ri->s_type);
1155         if ((ri->scheme && strcmp(ri->scheme, "file") == 0) &&
1156                         (ri->mime && strcmp(ri->mime, "NULL") != 0)) {
1157                 query = __make_query(query, ri->op, "NULL", ri->mime,
1158                                 ri->m_type, ri->s_type);
1159         }
1160         query = _svc_db_query_builder_build(query);
1161         _svc_db_exec_query(query, &info->list, info->uid);
1162         FREE_AND_NULL(query);
1163
1164         if (ri->category)
1165                 __get_list_with_category(ri->category, &info->list, info->uid);
1166         __get_list_with_submode(ri->op, ri->win_id, &info->list, info->uid);
1167
1168         if (g_slist_length(info->list) > 1)
1169                 info->uri_r_info = ri->scheme;
1170
1171         return AUL_SVC_RET_OK;
1172 }
1173
1174 static int __resolution_post(resolution_info_t *info)
1175 {
1176         int ret = AUL_SVC_RET_OK;
1177         int count;
1178
1179         if (info->appid) {
1180                 __put_cache(info->checksum, info->appid, info->uid);
1181                 goto end;
1182         }
1183
1184         count = g_slist_length(info->list);
1185         _D("count: %d", count);
1186         if (count == 1) {
1187                 info->appid = strdup((const char *)info->list->data);
1188                 if (info->appid == NULL) {
1189                         _E("Out of memory");
1190                         ret = AUL_SVC_RET_ERROR;
1191                         goto end;
1192                 }
1193                 __put_cache(info->checksum, info->appid, info->uid);
1194         } else if (count < 1) {
1195                 __put_cache(info->checksum, "^", info->uid);
1196                 ret = AUL_SVC_RET_ENOMATCH;
1197         } else {
1198                 bundle_add(info->b, AUL_SVC_K_URI_R_INFO, info->uri_r_info);
1199                 __put_cache_with_info(info->checksum, info->uri_r_info,
1200                                 info->uid);
1201                 info->appid = strdup(APP_SELECTOR);
1202                 if (info->appid == NULL) {
1203                         _E("Out of memory");
1204                         ret = AUL_SVC_RET_ERROR;
1205                 }
1206         }
1207
1208 end:
1209         __free_pkg_list(info->list);
1210         __free_resolve_info_data(&info->ri);
1211         g_free(info->checksum);
1212         return ret;
1213 }
1214
1215 static int __get_appid(bundle *b, uid_t uid, char **appid)
1216 {
1217         static const resolution_handler handlers[] = {
1218                 __resolution_pre,
1219                 __resolution_uri,
1220                 __resolution_scheme_and_host,
1221                 __resolution_scheme,
1222                 __resolution_post,
1223         };
1224         resolution_info_t info = { 0, };
1225         char *id;
1226         char *op;
1227         int ret;
1228         int i;
1229
1230         if (b == NULL || appid == NULL) {
1231                 _E("Invalid parameter");
1232                 return AUL_SVC_RET_EINVAL;
1233         }
1234
1235         op = (char *)aul_svc_get_operation(b);
1236         id = (char *)aul_svc_get_pkgname(b);
1237         if (id) {
1238                 if (!op)
1239                         aul_svc_set_operation(b, AUL_SVC_OPERATION_DEFAULT);
1240                 *appid = strdup(id);
1241                 if (*appid == NULL) {
1242                         _E("Out of memory");
1243                         return AUL_SVC_RET_ERROR;
1244                 }
1245                 return AUL_SVC_RET_OK;
1246         }
1247
1248         if (TIZEN_FEATURE_SHARE_PANEL &&
1249                         (op && (!strcmp(op, AUL_SVC_OPERATION_SHARE) ||
1250                          !strcmp(op, AUL_SVC_OPERATION_MULTI_SHARE) ||
1251                          !strcmp(op, AUL_SVC_OPERATION_SHARE_TEXT)))) {
1252                 *appid = strdup(SHARE_PANEL);
1253                 if (*appid == NULL) {
1254                         _E("Out of memory");
1255                         return AUL_SVC_RET_ERROR;
1256                 }
1257                 return AUL_SVC_RET_OK;
1258         }
1259
1260         info.b = b;
1261         info.uid = uid;
1262
1263         for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1264                 if (handlers[i]) {
1265                         ret = handlers[i](&info);
1266                         if (ret != AUL_SVC_RET_OK)
1267                                 return ret;
1268                 }
1269         }
1270
1271         *appid = info.appid;
1272
1273         return AUL_SVC_RET_OK;
1274 }
1275
1276 static int __run_service(bundle *b, int request_code,
1277                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
1278                 void *data, uid_t uid, bool sync)
1279 {
1280         char *appid = NULL;
1281         int ret;
1282
1283         ret = __get_appid(b, uid, &appid);
1284         if (ret != AUL_SVC_RET_OK) {
1285                 _E("Failed to get appid");
1286                 return ret;
1287         }
1288
1289         ret = __run_svc_with_pkgname(appid, b, request_code,
1290                         cbfunc, err_cb, data, uid, sync);
1291         free(appid);
1292
1293         return ret;
1294 }
1295
1296 API int aul_svc_run_service(bundle *b, int request_code,
1297                 aul_svc_res_fn cbfunc, void *data)
1298 {
1299         return __run_service(b, request_code, cbfunc, NULL, data,
1300                         getuid(), true);
1301 }
1302
1303 API int aul_svc_run_service_for_uid(bundle *b, int request_code,
1304                 aul_svc_res_fn cbfunc, void *data, uid_t uid)
1305 {
1306         return __run_service(b, request_code, cbfunc, NULL, data, uid, true);
1307 }
1308
1309 API int aul_svc_get_list(bundle *b, aul_svc_info_iter_fn iter_fn,
1310                 void *data)
1311 {
1312         return aul_svc_get_list_for_uid(b, iter_fn, data, getuid());
1313 }
1314
1315 API int aul_svc_get_list_for_uid(bundle *b, aul_svc_info_iter_fn iter_fn,
1316                 void *data, uid_t uid)
1317 {
1318         aul_svc_resolve_info_t info;
1319         char *pkgname = NULL;
1320         int pkg_count;
1321         int ret = -1;
1322
1323         GSList *pkg_list = NULL;
1324         GSList *iter = NULL;
1325         char *query = NULL;
1326         char *query2 = NULL;
1327
1328         if (b == NULL) {
1329                 _E("bundle is NULL");
1330                 return AUL_SVC_RET_EINVAL;
1331         }
1332
1333         if (iter_fn == NULL) {
1334                 _E("iter_fn is NULL");
1335                 return AUL_SVC_RET_EINVAL;
1336         }
1337
1338
1339         /* parse bundle */
1340         memset(&info, 0, sizeof(aul_svc_resolve_info_t));
1341         ret = __get_resolve_info(b, &info);
1342         if (ret < 0) {
1343                 __free_resolve_info_data(&info);
1344                 return ret;
1345         }
1346
1347         _D("operation - %s / shceme - %s / mime - %s", info.op, info.scheme,
1348            info.mime);
1349
1350         query2 = __make_query_with_collation(info.op, info.uri,
1351                         info.mime, info.m_type, info.s_type);
1352
1353         if (info.uri_r_info) {
1354                 query = __make_query(query, info.op, info.uri_r_info,
1355                         info.mime, info.m_type, info.s_type);
1356         }
1357
1358         query = __make_query(query, info.op, info.scheme,
1359                 info.mime, info.m_type, info.s_type);
1360
1361         query = __make_query(query, info.op, "*",
1362                 info.mime, info.m_type, info.s_type);
1363
1364         if (info.scheme && (strcmp(info.scheme, "file") == 0)
1365                 && info.mime && (strcmp(info.mime, "NULL") != 0)) {
1366                 query = __make_query(query, info.op, "NULL",
1367                         info.mime, info.m_type, info.s_type);
1368         }
1369
1370         query = _svc_db_query_builder_or(query2, query);
1371         query = _svc_db_query_builder_build(query);
1372         _svc_db_exec_query(query, &pkg_list, uid);
1373         if (query) {
1374                 free(query);
1375                 query = NULL;
1376         }
1377
1378         if (info.category)
1379                 __get_list_with_category(info.category, &pkg_list, uid);
1380
1381         __get_list_with_submode(info.op, info.win_id, &pkg_list, uid);
1382
1383         pkg_count = g_slist_length(pkg_list);
1384         if (pkg_count == 0) {
1385                 _E("Cannot find associated application");
1386
1387                 __free_resolve_info_data(&info);
1388                 return AUL_SVC_RET_ENOMATCH;
1389         }
1390
1391         for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
1392                 pkgname = iter->data;
1393                 SECURE_LOGD("PKGNAME : %s", pkgname);
1394                 if (iter_fn(pkgname, data) != 0)
1395                         break;
1396                 g_free(pkgname);
1397         }
1398
1399         g_slist_free(pkg_list);
1400         __free_resolve_info_data(&info);
1401
1402         return AUL_SVC_RET_OK;
1403 }
1404
1405 API int aul_svc_get_all_defapps(aul_svc_info_iter_fn iter_fn, void *data)
1406 {
1407         return aul_svc_get_all_defapps_for_uid(iter_fn, data, getuid());
1408 }
1409
1410 API int aul_svc_get_all_defapps_for_uid(aul_svc_info_iter_fn iter_fn,
1411                 void *data, uid_t uid)
1412 {
1413         char *pkgname = NULL;
1414         int ret = -1;
1415
1416         GSList *pkg_list = NULL;
1417         GSList *iter = NULL;
1418
1419         ret = _svc_db_get_list_with_all_defapps(&pkg_list, uid);
1420         if (ret < 0)
1421                 return ret;
1422
1423         for (iter = pkg_list; iter != NULL; iter = g_slist_next(iter)) {
1424                 pkgname = iter->data;
1425                 if (iter_fn(pkgname, data) != 0)
1426                         break;
1427                 g_free(pkgname);
1428         }
1429
1430         g_slist_free(pkg_list);
1431
1432         return AUL_SVC_RET_OK;
1433 }
1434
1435 API const char *aul_svc_get_operation(bundle *b)
1436 {
1437         return bundle_get_val(b, AUL_SVC_K_OPERATION);
1438 }
1439
1440 API const char *aul_svc_get_uri(bundle *b)
1441 {
1442         return bundle_get_val(b, AUL_SVC_K_URI);
1443 }
1444
1445 API const char *aul_svc_get_mime(bundle *b)
1446 {
1447         return bundle_get_val(b, AUL_SVC_K_MIME);
1448 }
1449
1450 API const char *aul_svc_get_data(bundle *b, const char *key)
1451 {
1452         return bundle_get_val(b, key);
1453 }
1454
1455 API const char **aul_svc_get_data_array(bundle *b, const char *key, int *len)
1456 {
1457         return bundle_get_str_array(b, key, len);
1458 }
1459
1460 API const char *aul_svc_get_pkgname(bundle *b)
1461 {
1462         return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
1463 }
1464
1465 API const char *aul_svc_get_appid(bundle *b)
1466 {
1467         return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
1468 }
1469
1470 API const char *aul_svc_get_category(bundle *b)
1471 {
1472         return bundle_get_val(b, AUL_SVC_K_CATEGORY);
1473 }
1474
1475 API const char *aul_svc_get_launch_mode(bundle *b)
1476 {
1477         return bundle_get_val(b, AUL_SVC_K_LAUNCH_MODE);
1478 }
1479
1480 API int aul_svc_create_result_bundle(bundle *inb, bundle **outb)
1481 {
1482         int ret = -1;
1483
1484         if (inb == NULL || outb == NULL) {
1485                 _E("bundle is NULL");
1486                 return AUL_SVC_RET_EINVAL;
1487         }
1488
1489         ret = aul_create_result_bundle(inb, outb);
1490
1491         /* add additional bundle */
1492         /*  bundle_add(outb, " ", " ");  */
1493
1494         if (ret == AUL_R_OK)
1495                 ret = AUL_SVC_RET_OK;
1496         else if (ret == AUL_R_EINVAL)
1497                 ret = AUL_SVC_RET_EINVAL;
1498         else if (ret == AUL_R_ECANCELED)
1499                 ret = AUL_SVC_RET_ECANCELED;
1500         else
1501                 ret = AUL_SVC_RET_ERROR;
1502
1503         return ret;
1504 }
1505
1506 API int aul_svc_send_result(bundle *b, aul_svc_result_val result)
1507 {
1508         int ret;
1509         char tmp[MAX_LOCAL_BUFSZ];
1510
1511         if (b == NULL) {
1512                 _E("aul_svc_send_result is NULL");
1513                 return AUL_SVC_RET_EINVAL;
1514         }
1515
1516         /* add result_code to bundle */
1517         snprintf(tmp, MAX_LOCAL_BUFSZ, "%d", (int)result);
1518         ret = __set_bundle(b, AUL_SVC_K_RES_VAL, tmp);
1519         if (ret < 0)
1520                 return AUL_SVC_RET_ERROR;
1521
1522         if (result == AUL_SVC_RES_CANCEL)
1523                 ret = aul_send_result(b, 1);
1524         else
1525                 ret = aul_send_result(b, 0);
1526
1527         /* remove result_code from bundle */
1528         bundle_del(b, AUL_SVC_K_RES_VAL);
1529
1530         return ret;
1531 }
1532
1533 API int aul_svc_set_defapp(const char *op, const char *mime_type,
1534                                 const char *uri, const char *defapp)
1535 {
1536         return aul_svc_set_defapp_for_uid(op, mime_type, uri, defapp, getuid());
1537 }
1538
1539 API int aul_svc_set_defapp_for_uid(const char *op, const char *mime_type,
1540                                 const char *uri, const char *defapp, uid_t uid)
1541 {
1542         int ret;
1543
1544         if (op == NULL || defapp == NULL)
1545                 return AUL_SVC_RET_EINVAL;
1546
1547         ret = _svc_db_add_app(op, mime_type, uri, defapp, uid);
1548         if (ret < 0)
1549                 return AUL_SVC_RET_ERROR;
1550
1551         return AUL_SVC_RET_OK;
1552 }
1553
1554 API int aul_svc_unset_defapp(const char *defapp)
1555 {
1556         return aul_svc_unset_defapp_for_uid(defapp, getuid());
1557 }
1558
1559 API int aul_svc_unset_defapp_for_uid(const char *defapp, uid_t uid)
1560 {
1561         int ret;
1562
1563         if (defapp == NULL)
1564                 return AUL_SVC_RET_EINVAL;
1565
1566         ret = _svc_db_delete_with_pkgname(defapp, uid);
1567
1568         if (ret < 0)
1569                 return AUL_SVC_RET_ERROR;
1570
1571         return AUL_SVC_RET_OK;
1572 }
1573
1574 API int aul_svc_unset_all_defapps()
1575 {
1576         return aul_svc_unset_all_defapps_for_uid(getuid());
1577 }
1578
1579 API int aul_svc_unset_all_defapps_for_uid(uid_t uid)
1580 {
1581         int ret;
1582
1583         ret = _svc_db_delete_all(uid);
1584
1585         if (ret < 0)
1586                 return AUL_SVC_RET_ERROR;
1587
1588         __invalidate_cache(uid);
1589         return AUL_SVC_RET_OK;
1590 }
1591
1592 API int aul_svc_is_defapp(const char *pkg_name)
1593 {
1594         return aul_svc_is_defapp_for_uid(pkg_name, getuid());
1595 }
1596
1597 API int aul_svc_is_defapp_for_uid(const char *pkg_name, uid_t uid)
1598 {
1599         return _svc_db_is_defapp(pkg_name, uid);
1600 }
1601
1602 API int aul_svc_data_is_array(bundle *b, const char *key)
1603 {
1604         int type;
1605         type = bundle_get_type(b, key);
1606
1607         if (type <= 0)
1608                 return 0;
1609
1610         if (type & BUNDLE_TYPE_ARRAY)
1611                 return 1;
1612         return 0;
1613 }
1614
1615 API int aul_svc_allow_transient_app(bundle *b, int wid)
1616 {
1617         char win_id[MAX_LOCAL_BUFSZ];
1618
1619         snprintf(win_id, MAX_LOCAL_BUFSZ, "%d", wid);
1620
1621         if (b == NULL) {
1622                 _E("bundle is NULL");
1623                 return AUL_SVC_RET_EINVAL;
1624         }
1625
1626         return __set_bundle(b, AUL_SVC_K_WIN_ID, win_id);
1627 }
1628
1629 API int aul_svc_request_transient_app(bundle *b, int callee_wid,
1630                                 aul_svc_host_res_fn cbfunc, void *data)
1631 {
1632         return 0;
1633 }
1634
1635 API int aul_svc_subapp_terminate_request_pid(int pid)
1636 {
1637         int cpid = getpid();
1638         int lcnt;
1639         int *lpids = NULL;
1640         int i;
1641
1642         aul_app_group_get_leader_pids(&lcnt, &lpids);
1643         for (i = 0; i < lcnt; i++) {
1644                 if (lpids[i] == cpid) {
1645                         int cnt;
1646                         int *pids = NULL;
1647
1648                         aul_app_group_get_group_pids(cpid, &cnt, &pids);
1649
1650                         if (cnt == 0) {
1651                                 free(lpids);
1652                                 if (pids)
1653                                         free(pids);
1654
1655                                 return aul_subapp_terminate_request_pid(pid);
1656                         }
1657
1658                         if (pids != NULL)
1659                                 free(pids);
1660                         break;
1661                 }
1662         }
1663
1664         if (lpids != NULL)
1665                 free(lpids);
1666
1667         return aul_app_group_clear_top();
1668 }
1669
1670 API int aul_send_service_result(bundle *b)
1671 {
1672         return aul_send_result(b, 0);
1673 }
1674
1675 API int aul_svc_subscribe_launch_result(bundle *b, const char *result)
1676 {
1677         if (b == NULL) {
1678                 _E("bundle is NULL");
1679                 return AUL_SVC_RET_EINVAL;
1680         }
1681
1682         return __set_bundle(b, result, "1");
1683 }
1684
1685 API int aul_svc_set_loader_id(bundle *b, int loader_id)
1686 {
1687         char tmp[MAX_LOCAL_BUFSZ];
1688
1689         if (b == NULL) {
1690                 _E("bundle is NULL");
1691                 return AUL_SVC_RET_EINVAL;
1692         }
1693
1694         if (loader_id <= 0) {
1695                 _E("invalid loader id");
1696                 return AUL_SVC_RET_EINVAL;
1697         }
1698
1699         snprintf(tmp, sizeof(tmp), "%d", loader_id);
1700         return __set_bundle(b, AUL_K_LOADER_ID, tmp);
1701 }
1702
1703 API int aul_svc_set_loader_name(bundle *b, const char *loader_name)
1704 {
1705         if (b == NULL) {
1706                 _E("bundle is NULL");
1707                 return AUL_SVC_RET_EINVAL;
1708         }
1709
1710         if (!loader_name) {
1711                 _E("invalid loader name");
1712                 return AUL_SVC_RET_EINVAL;
1713         }
1714
1715         return __set_bundle(b, AUL_K_LOADER_NAME, loader_name);
1716 }
1717
1718 API int aul_svc_set_background_launch(bundle *b, int enabled)
1719 {
1720         if (b == NULL)
1721                 return AUL_R_EINVAL;
1722
1723         if (bundle_get_type(b, AUL_SVC_K_BG_LAUNCH) != BUNDLE_TYPE_NONE)
1724                 bundle_del(b, AUL_SVC_K_BG_LAUNCH);
1725
1726         if (enabled)
1727                 bundle_add_str(b, AUL_SVC_K_BG_LAUNCH, "enable");
1728
1729         return AUL_R_OK;
1730 }
1731
1732 API int aul_svc_set_alias_appid(const char *alias_appid, const char *appid)
1733 {
1734         return aul_svc_set_alias_appid_for_uid(alias_appid, appid, getuid());
1735 }
1736
1737 API int aul_svc_set_alias_appid_for_uid(const char *alias_appid,
1738                 const char *appid, uid_t uid)
1739 {
1740         int ret;
1741
1742         ret = _svc_db_add_alias_appid(alias_appid, appid, uid);
1743         if (ret < 0)
1744                 return AUL_SVC_RET_ERROR;
1745
1746         return AUL_SVC_RET_OK;
1747 }
1748
1749 API int aul_svc_unset_alias_appid(const char *alias_appid)
1750 {
1751         return aul_svc_unset_alias_appid_for_uid(alias_appid, getuid());
1752 }
1753
1754 API int aul_svc_unset_alias_appid_for_uid(const char *alias_appid, uid_t uid)
1755 {
1756         int ret;
1757
1758         ret = _svc_db_delete_alias_appid(alias_appid, uid);
1759         if (ret < 0)
1760                 return AUL_SVC_RET_ERROR;
1761
1762         return AUL_SVC_RET_OK;
1763 }
1764
1765 API int aul_svc_foreach_alias_info(void (*callback)(const char *alias_appid,
1766                         const char *appid, void *data), void *user_data)
1767 {
1768         return aul_svc_foreach_alias_info_for_uid(callback, getuid(),
1769                         user_data);
1770 }
1771
1772 API int aul_svc_foreach_alias_info_for_uid(void (*callback)(
1773                         const char *alias_appid, const char *appid,
1774                         void *data), uid_t uid, void *user_data)
1775 {
1776         int ret;
1777
1778         if (callback == NULL) {
1779                 _E("Invalid parameter");
1780                 return AUL_SVC_RET_EINVAL;
1781         }
1782
1783         ret = _svc_db_foreach_alias_info(callback, uid, user_data);
1784         if (ret < 0)
1785                 return AUL_SVC_RET_ERROR;
1786
1787         return AUL_SVC_RET_OK;
1788 }
1789
1790 API int aul_svc_enable_alias_info(const char *appid)
1791 {
1792         return aul_svc_enable_alias_info_for_uid(appid, getuid());
1793 }
1794
1795 API int aul_svc_enable_alias_info_for_uid(const char *appid, uid_t uid)
1796 {
1797         int ret;
1798
1799         ret = _svc_db_enable_alias_info(appid, uid);
1800         if (ret < 0)
1801                 return AUL_SVC_RET_ERROR;
1802
1803         return AUL_SVC_RET_OK;
1804 }
1805
1806 API int aul_svc_disable_alias_info(const char *appid)
1807 {
1808         return aul_svc_disable_alias_info_for_uid(appid, getuid());
1809 }
1810
1811 API int aul_svc_disable_alias_info_for_uid(const char *appid, uid_t uid)
1812 {
1813         int ret;
1814
1815         ret = _svc_db_disable_alias_info(appid, uid);
1816         if (ret < 0)
1817                 return AUL_SVC_RET_ERROR;
1818
1819         return AUL_SVC_RET_OK;
1820 }
1821
1822 API int aul_svc_get_appid_by_alias_appid(const char *alias_appid, char **appid)
1823 {
1824         return aul_svc_get_appid_by_alias_appid_for_uid(alias_appid,
1825                         appid, getuid());
1826 }
1827
1828 API int aul_svc_get_appid_by_alias_appid_for_uid(const char *alias_appid,
1829                 char **appid, uid_t uid)
1830 {
1831         int ret;
1832
1833         ret = _svc_db_get_appid_from_alias_info(alias_appid, appid, uid);
1834         if (ret < 0)
1835                 return AUL_SVC_RET_ERROR;
1836
1837         return AUL_SVC_RET_OK;
1838 }
1839
1840 API int aul_svc_foreach_alias_info_by_appid(int (*callback)(
1841                         const char *alias_appid, const char *appid, void *data),
1842                 const char *appid, void *user_data)
1843 {
1844         return aul_svc_foreach_alias_info_by_appid_for_uid(callback, appid,
1845                         getuid(), user_data);
1846 }
1847
1848 API int aul_svc_foreach_alias_info_by_appid_for_uid(int (*callback)(
1849                         const char *alias_appid, const char *appid, void *data),
1850                 const char *appid, uid_t uid, void *user_data)
1851 {
1852         int ret;
1853
1854         if (callback == NULL || appid == NULL) {
1855                 _E("Invalid parameter");
1856                 return AUL_SVC_RET_EINVAL;
1857         }
1858
1859         ret = _svc_db_foreach_alias_info_by_appid(callback, appid,
1860                         uid, user_data);
1861         if (ret < 0)
1862                 return AUL_SVC_RET_ERROR;
1863
1864         return AUL_SVC_RET_OK;
1865 }
1866
1867 API int aul_svc_foreach_allowed_info(int (*callback)(const char *appid,
1868                         const char *allowed_appid, void *data), void *user_data)
1869 {
1870         return aul_svc_foreach_allowed_info_for_uid(callback,
1871                         getuid(), user_data);
1872 }
1873
1874 API int aul_svc_foreach_allowed_info_for_uid(int (*callback)(const char *appid,
1875                         const char *allowed_appid, void *data),
1876                 uid_t uid, void *user_data)
1877 {
1878         int ret;
1879
1880         if (callback == NULL) {
1881                 _E("Invalid parameter");
1882                 return AUL_SVC_RET_EINVAL;
1883         }
1884
1885         ret = _svc_db_foreach_allowed_info(callback, uid, user_data);
1886         if (ret < 0)
1887                 return AUL_SVC_RET_ERROR;
1888
1889         return AUL_SVC_RET_OK;
1890 }
1891
1892 API int aul_svc_foreach_allowed_info_by_appid(int (*callback)(
1893                         const char *appid, const char *allowed_appid, void *data),
1894                 const char *appid, void *user_data)
1895 {
1896         return aul_svc_foreach_allowed_info_by_appid_for_uid(callback,
1897                         appid, getuid(), user_data);
1898 }
1899
1900 API int aul_svc_foreach_allowed_info_by_appid_for_uid(int (*callback)(
1901                         const char *appid, const char *allowed_appid, void *data),
1902                 const char *appid, uid_t uid, void *user_data)
1903 {
1904         int ret;
1905
1906         if (callback == NULL || appid == NULL) {
1907                 _E("Invalid parameter");
1908                 return AUL_SVC_RET_EINVAL;
1909         }
1910
1911         ret = _svc_db_foreach_allowed_info_by_appid(callback, appid,
1912                         uid, user_data);
1913         if (ret < 0)
1914                 return AUL_SVC_RET_ERROR;
1915
1916         return AUL_SVC_RET_OK;
1917 }
1918
1919 API const char *aul_svc_get_instance_id(bundle *b)
1920 {
1921         return bundle_get_val(b, AUL_K_INSTANCE_ID);
1922 }
1923
1924 API int aul_svc_set_instance_id(bundle *b, const char *instance_id)
1925 {
1926         if (b == NULL || instance_id == NULL) {
1927                 _E("Invalid parameter");
1928                 return AUL_SVC_RET_EINVAL;
1929         }
1930
1931         return __set_bundle(b, AUL_K_INSTANCE_ID, instance_id);
1932 }
1933
1934 API int aul_svc_run_service_async(bundle *b, int request_code,
1935                 aul_svc_res_fn cbfunc, void *data)
1936 {
1937         return __run_service(b, request_code, cbfunc, NULL, data,
1938                         getuid(), false);
1939 }
1940
1941 API int aul_svc_run_service_async_for_uid(bundle *b, int request_code,
1942                 aul_svc_res_fn cbfunc, void *data, uid_t uid)
1943 {
1944         return __run_service(b, request_code, cbfunc, NULL, data, uid, false);
1945 }
1946
1947 API int aul_svc_send_launch_request(bundle *b, int request_code,
1948                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
1949                 void *user_data)
1950 {
1951         return aul_svc_send_launch_request_for_uid(b, request_code,
1952                         cbfunc, err_cb, user_data, getuid());
1953 }
1954
1955 API int aul_svc_send_launch_request_for_uid(bundle *b, int request_code,
1956                 aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
1957                 void *user_data, uid_t uid)
1958 {
1959         return __run_service(b, request_code, cbfunc, err_cb, user_data,
1960                         uid, false);
1961 }
1962
1963 API int aul_svc_send_launch_request_sync_for_uid(bundle *b, int request_code,
1964                 bundle **res_b, aul_svc_result_val *res, uid_t uid)
1965 {
1966         char *pkgname = NULL;
1967         const char *val;
1968         char *appid = NULL;
1969         int ret;
1970
1971         ret = __get_appid(b, uid, &appid);
1972         if (ret != AUL_SVC_RET_OK) {
1973                 _E("Failed to find appid");
1974                 return ret;
1975         }
1976
1977         pkgname = appid;
1978         __verify_request(b, &pkgname);
1979
1980         ret = aul_send_launch_request_sync_for_uid(pkgname, b, uid, res_b);
1981         if (ret > 0) {
1982                 val = bundle_get_val(*res_b, AUL_SVC_K_RES_VAL);
1983                 *res = (val == NULL) ? AUL_SVC_RES_NOT_OK : atoi(val);
1984         } else {
1985                 ret = __error_convert(ret);
1986                 *res = AUL_SVC_RES_CANCEL;
1987         }
1988         free(appid);
1989
1990         return ret;
1991 }
1992
1993 API int aul_svc_info_create(bundle *b, aul_svc_info_h *h)
1994 {
1995         aul_svc_resolve_info_t *info;
1996         int r;
1997
1998         if (!b || !h) {
1999                 _E("Invalid parameter");
2000                 return AUL_SVC_RET_EINVAL;
2001         }
2002
2003         info = calloc(1, sizeof(aul_svc_resolve_info_t));
2004         if (!info) {
2005                 _E("Out of memory");
2006                 return AUL_SVC_RET_ERROR;
2007         }
2008
2009         r = __get_resolve_info(b, info);
2010         if (r < 0) {
2011                 _E("Failed to get resolving info");
2012                 __free_resolve_info_data(info);
2013                 free(info);
2014                 return r;
2015         }
2016
2017         *h = info;
2018
2019         return AUL_SVC_RET_OK;
2020 }
2021
2022 API int aul_svc_info_get_operation(aul_svc_info_h h, char **operation)
2023 {
2024         aul_svc_resolve_info_t *info;
2025
2026         if (!h || !operation) {
2027                 _E("Invalid parameter");
2028                 return AUL_SVC_RET_EINVAL;
2029         }
2030
2031         info = (aul_svc_resolve_info_t *)h;
2032         *operation = strdup(info->op ? info->op : "NULL");
2033         if (*operation == NULL) {
2034                 _E("Failed to duplicate operation");
2035                 return AUL_SVC_RET_ERROR;
2036         }
2037
2038         return AUL_SVC_RET_OK;
2039 }
2040
2041 API int aul_svc_info_get_uri(aul_svc_info_h h, char **uri)
2042 {
2043         aul_svc_resolve_info_t *info;
2044
2045         if (!h || !uri) {
2046                 _E("Invalid parameter");
2047                 return AUL_SVC_RET_EINVAL;
2048         }
2049
2050         info = (aul_svc_resolve_info_t *)h;
2051         *uri = strdup(info->uri ? info->uri : "NULL");
2052         if (*uri == NULL) {
2053                 _E("Failed to duplicate URI");
2054                 return AUL_SVC_RET_ERROR;
2055         }
2056
2057         return AUL_SVC_RET_OK;
2058 }
2059
2060 API int aul_svc_info_get_uri_scheme(aul_svc_info_h h, char **uri_scheme)
2061 {
2062         aul_svc_resolve_info_t *info;
2063
2064         if (!h || !uri_scheme) {
2065                 _E("Invalid parameter");
2066                 return AUL_SVC_RET_EINVAL;
2067         }
2068
2069         info = (aul_svc_resolve_info_t *)h;
2070         *uri_scheme = strdup(info->scheme ? info->scheme : "NULL");
2071         if (*uri_scheme == NULL) {
2072                 _E("Failed to duplicate URI scheme");
2073                 return AUL_SVC_RET_ERROR;
2074         }
2075
2076         return AUL_SVC_RET_OK;
2077 }
2078
2079 API int aul_svc_info_get_uri_host(aul_svc_info_h h, char **uri_host)
2080 {
2081         aul_svc_resolve_info_t *info;
2082
2083         if (!h || !uri_host) {
2084                 _E("Invalid parameter");
2085                 return AUL_SVC_RET_EINVAL;
2086         }
2087
2088         info = (aul_svc_resolve_info_t *)h;
2089         *uri_host = strdup(info->host ? info->host : "NULL");
2090         if (*uri_host == NULL) {
2091                 _E("Failed to duplicate URI host");
2092                 return AUL_SVC_RET_ERROR;
2093         }
2094
2095         return AUL_SVC_RET_OK;
2096 }
2097
2098 API int aul_svc_info_get_mime(aul_svc_info_h h, char **mime)
2099 {
2100         aul_svc_resolve_info_t *info;
2101
2102         if (!h || !mime) {
2103                 _E("Invalid parameter");
2104                 return AUL_SVC_RET_EINVAL;
2105         }
2106
2107         info = (aul_svc_resolve_info_t *)h;
2108         *mime = strdup(info->mime ? info->mime : "NULL");
2109         if (*mime == NULL) {
2110                 _E("Failed to duplicate MIME-Type");
2111                 return AUL_SVC_RET_ERROR;
2112         }
2113
2114         return AUL_SVC_RET_OK;
2115 }
2116
2117 API int aul_svc_info_get_mime_type(aul_svc_info_h h, char **mime_type)
2118 {
2119         aul_svc_resolve_info_t *info;
2120
2121         if (!h || !mime_type) {
2122                 _E("Invalid parameter");
2123                 return AUL_SVC_RET_EINVAL;
2124         }
2125
2126         info = (aul_svc_resolve_info_t *)h;
2127         *mime_type = strdup(info->m_type ? info->m_type : "NULL");
2128         if (*mime_type == NULL) {
2129                 _E("Failed to duplicate the type of MIME-Type");
2130                 return AUL_SVC_RET_ERROR;
2131         }
2132
2133         return AUL_SVC_RET_OK;
2134 }
2135
2136 API int aul_svc_info_get_mime_subtype(aul_svc_info_h h, char **mime_subtype)
2137 {
2138         aul_svc_resolve_info_t *info;
2139
2140         if (!h || !mime_subtype) {
2141                 _E("Invalid parameter");
2142                 return AUL_SVC_RET_EINVAL;
2143         }
2144
2145         info = (aul_svc_resolve_info_t *)h;
2146         *mime_subtype = strdup(info->s_type ? info->s_type : "NULL");
2147         if (*mime_subtype == NULL) {
2148                 _E("Failed to duplicate the subtype of MIME-Type");
2149                 return AUL_SVC_RET_ERROR;
2150         }
2151
2152         return AUL_SVC_RET_OK;
2153 }
2154
2155 API int aul_svc_info_destroy(aul_svc_info_h h)
2156 {
2157         aul_svc_resolve_info_t *info;
2158
2159         if (!h) {
2160                 _E("Invalid parameter");
2161                 return AUL_SVC_RET_EINVAL;
2162         }
2163
2164         info = (aul_svc_resolve_info_t *)h;
2165         __free_resolve_info_data(info);
2166         free(info);
2167
2168         return AUL_SVC_RET_OK;
2169 }
2170
2171 API int aul_svc_set_caller_instance_id(bundle *b, const char *instance_id)
2172 {
2173         if (!b) {
2174                 _E("Invalid parameter");
2175                 return AUL_SVC_RET_EINVAL;
2176         }
2177
2178         return __set_bundle(b, AUL_K_CALLER_INSTANCE_ID, instance_id);
2179 }
2180
2181 API int aul_svc_set_comp_id(bundle *b, const char *comp_id)
2182 {
2183         if (!b) {
2184                 _E("Invalid parameter");
2185                 return AUL_SVC_RET_EINVAL;
2186         }
2187
2188         return __set_bundle(b, AUL_K_COMPONENT_ID, comp_id);
2189 }
2190
2191 API const char *aul_svc_get_comp_id(bundle *b)
2192 {
2193         return bundle_get_val(b, AUL_K_COMPONENT_ID);
2194 }
2195
2196 static void __foreach_group_info(aul_app_group_info_h info, void *data)
2197 {
2198         int *cnt = (int *)data;
2199
2200         (*cnt)++;
2201 }
2202
2203 API int aul_svc_subapp_terminate_request(bundle *b, int pid)
2204 {
2205         const char *caller_inst_id;
2206         const char *inst_id;
2207         char buf[512] = { 0, };
2208         int cnt = 0;
2209         int ret;
2210
2211         if (!b || pid < 0) {
2212                 _E("Invalid parameter");
2213                 return AUL_SVC_RET_EINVAL;
2214         }
2215
2216         inst_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
2217         if (!inst_id) {
2218                 _E("Invalid request");
2219                 return AUL_SVC_RET_EINVAL;
2220         }
2221
2222         caller_inst_id = bundle_get_val(b, AUL_K_CALLER_INSTANCE_ID);
2223         if (!caller_inst_id) {
2224                 ret = aul_app_get_instance_id_bypid(getpid(), buf, sizeof(buf));
2225                 if (ret != AUL_R_OK) {
2226                         _E("Failed to get caller instance ID");
2227                         return AUL_SVC_RET_ERROR;
2228                 }
2229                 caller_inst_id = buf;
2230         }
2231
2232         aul_app_group_foreach_group_info(caller_inst_id,
2233                         __foreach_group_info, (void *)&cnt);
2234         if (cnt == 0)
2235                 return aul_subapp_terminate_request(inst_id, pid);
2236
2237         return aul_app_group_clear_top();
2238 }