2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <linux/limits.h>
28 #include <bundle_internal.h>
29 #include <pkgmgr-info.h>
31 #include <aul_svc_internal.h>
33 #include "appcore_base.h"
34 #include "appcore_base_private.h"
35 #include "appcore_base_control.h"
37 struct appcore_base_control_s {
39 appcore_base_control_cb callback;
43 struct control_info_s {
54 static GList *__controls;
55 static GList *__control_infos;
56 static bool __control_info_initialized;
58 static void __destroy_control_info(gpointer data)
60 struct control_info_s *info = (struct control_info_s *)data;
65 if (info->mime_subtype)
66 free(info->mime_subtype);
68 free(info->mime_type);
74 free(info->uri_scheme);
78 free(info->operation);
84 static struct control_info_s *__create_control_info(const char *id,
85 const char *operation, const char *mime,
88 struct control_info_s *info;
90 info = calloc(1, sizeof(struct control_info_s));
92 _ERR("Out of memory");
96 info->id = strdup(id);
98 _ERR("Failed to duplicate app-control ID");
103 info->operation = strdup(operation);
104 if (!info->operation) {
105 _ERR("Failed to duplicate app-control operation");
106 __destroy_control_info(info);
110 info->mime = strdup(mime ? mime : "NULL");
112 _ERR("Failed to duplicate app-control MIME-type");
113 __destroy_control_info(info);
117 info->uri = strdup(uri ? uri : "NULL");
119 _ERR("Failed to duplicate app-control URI");
120 __destroy_control_info(info);
127 static struct control_info_s *__create_control_info_from_bundle(bundle *b)
129 struct control_info_s *info;
130 aul_svc_info_h svc_info;
133 r = aul_svc_info_create(b, &svc_info);
134 if (r != AUL_SVC_RET_OK)
137 info = calloc(1, sizeof(struct control_info_s));
139 _ERR("Out of memory");
143 r = aul_svc_info_get_operation(svc_info, &info->operation);
144 if (r != AUL_SVC_RET_OK)
147 r = aul_svc_info_get_uri(svc_info, &info->uri);
148 if (r != AUL_SVC_RET_OK)
151 r = aul_svc_info_get_uri_scheme(svc_info, &info->uri_scheme);
152 if (r != AUL_SVC_RET_OK)
155 r = aul_svc_info_get_uri_host(svc_info, &info->uri_host);
156 if (r != AUL_SVC_RET_OK)
159 r = aul_svc_info_get_mime(svc_info, &info->mime);
160 if (r != AUL_SVC_RET_OK)
163 r = aul_svc_info_get_mime_type(svc_info, &info->mime_type);
164 if (r != AUL_SVC_RET_OK)
167 r = aul_svc_info_get_mime_subtype(svc_info, &info->mime_subtype);
168 if (r != AUL_SVC_RET_OK)
171 aul_svc_info_destroy(svc_info);
175 __destroy_control_info(info);
176 aul_svc_info_destroy(svc_info);
181 static gint __compare_control_infos(gconstpointer a, gconstpointer b)
183 struct control_info_s *a_info = (struct control_info_s *)a;
184 struct control_info_s *b_info = (struct control_info_s *)b;
187 if (strcmp(a_info->operation, b_info->operation) != 0)
190 if (!strcmp(a_info->uri, b_info->uri) &&
191 !strcmp(a_info->mime, b_info->mime))
194 if (!strcmp(a_info->uri, b_info->uri)) {
195 if (!strcmp(b_info->mime, "NULL") &&
196 !strcmp(b_info->mime_subtype, "%")) {
197 snprintf(mime, sizeof(mime), "%s/*",
199 if (!strcmp(a_info->mime, mime))
203 if (!strcmp(b_info->mime, "NULL") &&
204 !strcmp(b_info->mime_type, "%")) {
205 if (!strcmp(a_info->mime, "*/*"))
213 static struct control_info_s *__find_control_info(bundle *b)
215 struct control_info_s *info;
216 struct control_info_s b_info;
220 info = __create_control_info_from_bundle(b);
227 found = g_list_find_custom(__control_infos, &b_info,
228 __compare_control_infos);
230 __destroy_control_info(info);
235 if (strcmp(b_info.uri_scheme, "NULL") != 0 &&
236 strcmp(b_info.uri_host, "NULL") != 0) {
237 snprintf(uri, sizeof(uri), "%s://%s",
238 b_info.uri_scheme, b_info.uri_host);
240 found = g_list_find_custom(__control_infos, &b_info,
241 __compare_control_infos);
243 __destroy_control_info(info);
249 b_info.uri = info->uri_scheme;
250 found = g_list_find_custom(__control_infos, &b_info,
251 __compare_control_infos);
253 __destroy_control_info(info);
259 found = g_list_find_custom(__control_infos, &b_info,
260 __compare_control_infos);
262 __destroy_control_info(info);
267 if (!strcmp(b_info.uri_scheme, "file") &&
268 strcmp(b_info.mime, "NULL") != 0) {
270 found = g_list_find_custom(__control_infos, &b_info,
271 __compare_control_infos);
273 __destroy_control_info(info);
278 __destroy_control_info(info);
283 static int __foreach_app_control_cb(const char *operation,
284 const char *uri, const char *mime, const char *id,
287 struct control_info_s *info;
289 info = __create_control_info(id, operation, mime, uri);
293 __control_infos = g_list_append(__control_infos, info);
298 int appcore_base_control_init(void)
300 pkgmgrinfo_appinfo_h handle;
304 if (__control_info_initialized)
305 return APPCORE_BASE_ERROR_NONE;
307 r = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
309 _ERR("Failed to get application ID. result(%x)", r);
310 return APPCORE_BASE_ERROR_IO_ERROR;
313 r = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
314 if (r != PMINFO_R_OK) {
315 _ERR("Failed to get app info. result(%x)", r);
316 return APPCORE_BASE_ERROR_IO_ERROR;
319 r = pkgmgrinfo_appinfo_foreach_appcontrol_v2(handle,
320 __foreach_app_control_cb, NULL);
321 if (r != PMINFO_R_OK) {
322 _ERR("Failed to retrieve app-control. result(%x)", r);
323 pkgmgrinfo_appinfo_destroy_appinfo(handle);
324 return APPCORE_BASE_ERROR_IO_ERROR;
327 pkgmgrinfo_appinfo_destroy_appinfo(handle);
329 __control_info_initialized = true;
331 return APPCORE_BASE_ERROR_NONE;
334 void appcore_base_control_fini(void)
337 g_list_free_full(__controls,
338 (GDestroyNotify)appcore_base_control_remove);
342 if (__control_infos) {
343 g_list_free_full(__control_infos, __destroy_control_info);
344 __control_infos = NULL;
347 __control_info_initialized = false;
350 int appcore_base_control_invoke(bundle *b)
352 struct appcore_base_control_s *ctrl;
353 struct control_info_s *info;
357 _ERR("Invalid parameter");
358 return APPCORE_BASE_ERROR_INVALID_PARAMETER;
362 return APPCORE_BASE_ERROR_NONE;
364 info = __find_control_info(b);
366 return APPCORE_BASE_ERROR_NONE;
370 ctrl = (struct appcore_base_control_s *)iter->data;
371 if (!strcmp(ctrl->id, info->id))
372 ctrl->callback(b, ctrl->user_data);
374 iter = g_list_next(iter);
377 _DBG("[app-control] id(%s)", info->id);
378 return APPCORE_BASE_ERROR_NONE;
381 static bool __control_info_exists(const char *id)
383 struct control_info_s *info;
386 iter = __control_infos;
388 info = (struct control_info_s *)iter->data;
389 if (!strcmp(info->id, id))
392 iter = g_list_next(iter);
398 EXPORT_API int appcore_base_control_add(const char *id,
399 appcore_base_control_cb callback, void *user_data,
400 appcore_base_control_h *h)
402 struct appcore_base_control_s *ctrl;
405 if (!id || !callback || !h) {
406 _ERR("Invalid parameter");
407 return APPCORE_BASE_ERROR_INVALID_PARAMETER;
410 r = appcore_base_control_init();
412 _ERR("Failed to initialize app-control info");
416 if (!__control_info_exists(id)) {
417 _ERR("Failed to find control info(%s)", id);
418 return APPCORE_BASE_ERROR_KEY_NOT_FOUND;
421 ctrl = calloc(1, sizeof(struct appcore_base_control_s));
423 _ERR("Out of memory");
424 return APPCORE_BASE_ERROR_OUT_OF_MEMORY;
427 ctrl->id = strdup(id);
429 _ERR("Failed to duplicate app-control ID");
431 return APPCORE_BASE_ERROR_OUT_OF_MEMORY;
434 ctrl->callback = callback;
435 ctrl->user_data = user_data;
437 __controls = g_list_append(__controls, ctrl);
441 return APPCORE_BASE_ERROR_NONE;
444 EXPORT_API int appcore_base_control_remove(appcore_base_control_h h)
446 struct appcore_base_control_s *ctrl;
448 if (!h || !g_list_find(__controls, h)) {
449 _ERR("Invalid parameter");
450 return APPCORE_BASE_ERROR_INVALID_PARAMETER;
453 ctrl = (struct appcore_base_control_s *)h;
454 __controls = g_list_remove(__controls, ctrl);
460 return APPCORE_BASE_ERROR_NONE;