From 4cb2e1286c9e314e4b819d96e44d49bfe24f443e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Sun, 3 Feb 2019 18:39:40 +0900 Subject: [PATCH] Support handling of each app-control ID Requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/199252/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/app-core/+/199104/ - https://review.tizen.org/gerrit/#/c/platform/core/api/app-control/+/199105/ Change-Id: Ic02def5706302642d90c20a2f7bdde5700976f0e Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 4 +- include/appcore_base.h | 9 + include/appcore_base_control.h | 37 ++++ packaging/app-core.spec | 1 + src/base/appcore_base.c | 6 + src/base/appcore_base_control.c | 461 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 include/appcore_base_control.h create mode 100644 src/base/appcore_base_control.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 17f4d5b..a85c605 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,12 +29,14 @@ SET(SRCS_common src/legacy/appcore-rotation.c src/legacy/appcore-i18n.c src/base/appcore_base.c + src/base/appcore_base_control.c src/watchdog/appcore_watchdog.c) SET(HEADERS_common appcore-common.h appcore_base.h - appcore_watchdog.h) + appcore_watchdog.h + appcore_base_control.h) INCLUDE(FindPkgConfig) SET(APPCORE_PKG_CHECK_MODULES "gio-2.0 vconf sensor aul dlog capi-system-info") diff --git a/include/appcore_base.h b/include/appcore_base.h index 4d4ccea..760cade 100644 --- a/include/appcore_base.h +++ b/include/appcore_base.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -56,6 +57,14 @@ enum appcore_base_display_state { APPCORE_BASE_DISPLAY_STATE_OFF, }; +typedef enum { + APPCORE_BASE_ERROR_NONE = 0, + APPCORE_BASE_ERROR_INVALID_PARAMETER = -EINVAL, + APPCORE_BASE_ERROR_OUT_OF_MEMORY = -ENOMEM, + APPCORE_BASE_ERROR_KEY_NOT_FOUND = -ENOKEY, + APPCORE_BASE_ERROR_IO_ERROR = -EIO, +} appcore_base_error_e; + typedef int (*appcore_base_event_cb)(void *event, void *data); typedef void *appcore_base_event_h; diff --git a/include/appcore_base_control.h b/include/appcore_base_control.h new file mode 100644 index 0000000..ffc6832 --- /dev/null +++ b/include/appcore_base_control.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "appcore_base.h" + +typedef void *appcore_base_control_h; + +typedef void (*appcore_base_control_cb)(bundle *b, void *user_data); + +int appcore_base_control_init(void); + +void appcore_base_control_fini(void); + +int appcore_base_control_invoke(bundle *b); + +int appcore_base_control_add(const char *id, + appcore_base_control_cb callback, void *user_data, + appcore_base_control_h *h); + +int appcore_base_control_remove(appcore_base_control_h h); diff --git a/packaging/app-core.spec b/packaging/app-core.spec index 2e34380..5770ce1 100644 --- a/packaging/app-core.spec +++ b/packaging/app-core.spec @@ -186,6 +186,7 @@ rm -rf %{buildroot} %{_includedir}/appcore/appcore-common.h %{_includedir}/appcore/appcore_base.h %{_includedir}/appcore/appcore_watchdog.h +%{_includedir}/appcore/appcore_base_control.h %files ui %manifest %{name}.manifest diff --git a/src/base/appcore_base.c b/src/base/appcore_base.c index 27eee21..e276926 100644 --- a/src/base/appcore_base.c +++ b/src/base/appcore_base.c @@ -42,6 +42,7 @@ #include "appcore_base.h" #include "appcore_base_private.h" #include "appcore_watchdog.h" +#include "appcore_base_control.h" #define PATH_LOCALE "locale" #define RESOURCED_FREEZER_PATH "/Org/Tizen/ResourceD/Freezer" @@ -1085,6 +1086,8 @@ EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, vo if (__context.ops.set_i18n) __context.ops.set_i18n(__context.data); + appcore_base_control_init(); + if (__context.ops.create) { traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE"); r = __context.ops.create(__context.data); @@ -1120,6 +1123,7 @@ EXPORT_API void appcore_base_fini(void) } } + appcore_base_control_fini(); __unset_default_events(); if (__context.sid) { @@ -1256,6 +1260,8 @@ EXPORT_API int appcore_base_on_create(void) EXPORT_API int appcore_base_on_control(bundle *b) { + appcore_base_control_invoke(b); + return 0; } diff --git a/src/base/appcore_base_control.c b/src/base/appcore_base_control.c new file mode 100644 index 0000000..b096417 --- /dev/null +++ b/src/base/appcore_base_control.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appcore_base.h" +#include "appcore_base_private.h" +#include "appcore_base_control.h" + +struct appcore_base_control_s { + char *id; + appcore_base_control_cb callback; + void *user_data; +}; + +struct control_info_s { + char *id; + char *operation; + char *uri; + char *uri_scheme; + char *uri_host; + char *mime; + char *mime_type; + char *mime_subtype; +}; + +static GList *__controls; +static GList *__control_infos; +static bool __control_info_initialized; + +static void __destroy_control_info(gpointer data) +{ + struct control_info_s *info = (struct control_info_s *)data; + + if (!info) + return; + + if (info->mime_subtype) + free(info->mime_subtype); + if (info->mime_type) + free(info->mime_type); + if (info->mime) + free(info->mime); + if (info->uri_host) + free(info->uri_host); + if (info->uri_scheme) + free(info->uri_scheme); + if (info->uri) + free(info->uri); + if (info->operation) + free(info->operation); + if (info->id) + free(info->id); + free(info); +} + +static struct control_info_s *__create_control_info(const char *id, + const char *operation, const char *mime, + const char *uri) +{ + struct control_info_s *info; + + info = calloc(1, sizeof(struct control_info_s)); + if (!info) { + _ERR("Out of memory"); + return NULL; + } + + info->id = strdup(id); + if (!info->id) { + _ERR("Failed to duplicate app-control ID"); + free(info); + return NULL; + } + + info->operation = strdup(operation); + if (!info->operation) { + _ERR("Failed to duplicate app-control operation"); + __destroy_control_info(info); + return NULL; + } + + info->mime = strdup(mime ? mime : "NULL"); + if (!info->mime) { + _ERR("Failed to duplicate app-control MIME-type"); + __destroy_control_info(info); + return NULL; + } + + info->uri = strdup(uri ? uri : "NULL"); + if (!info->uri) { + _ERR("Failed to duplicate app-control URI"); + __destroy_control_info(info); + return NULL; + } + + return info; +} + +static struct control_info_s *__create_control_info_from_bundle(bundle *b) +{ + struct control_info_s *info; + aul_svc_info_h svc_info; + int r; + + r = aul_svc_info_create(b, &svc_info); + if (r != AUL_SVC_RET_OK) + return NULL; + + info = calloc(1, sizeof(struct control_info_s)); + if (!info) { + _ERR("Out of memory"); + goto err; + } + + r = aul_svc_info_get_operation(svc_info, &info->operation); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_uri(svc_info, &info->uri); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_uri_scheme(svc_info, &info->uri_scheme); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_uri_host(svc_info, &info->uri_host); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_mime(svc_info, &info->mime); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_mime_type(svc_info, &info->mime_type); + if (r != AUL_SVC_RET_OK) + goto err; + + r = aul_svc_info_get_mime_subtype(svc_info, &info->mime_subtype); + if (r != AUL_SVC_RET_OK) + goto err; + + aul_svc_info_destroy(svc_info); + + return info; +err: + __destroy_control_info(info); + aul_svc_info_destroy(svc_info); + + return NULL; +} + +static gint __compare_control_infos(gconstpointer a, gconstpointer b) +{ + struct control_info_s *a_info = (struct control_info_s *)a; + struct control_info_s *b_info = (struct control_info_s *)b; + char mime[256]; + + if (strcmp(a_info->operation, b_info->operation) != 0) + return -1; + + if (!strcmp(a_info->uri, b_info->uri) && + !strcmp(a_info->mime, b_info->mime)) + return 0; + + if (!strcmp(a_info->uri, b_info->uri)) { + if (!strcmp(b_info->mime, "NULL") && + !strcmp(b_info->mime_subtype, "%")) { + snprintf(mime, sizeof(mime), "%s/*", + b_info->mime_type); + if (!strcmp(a_info->mime, mime)) + return 0; + } + + if (!strcmp(b_info->mime, "NULL") && + !strcmp(b_info->mime_type, "%")) { + if (!strcmp(a_info->mime, "*/*")) + return 0; + } + } + + return -1; +} + +static struct control_info_s *__find_control_info(bundle *b) +{ + struct control_info_s *info; + struct control_info_s b_info; + char uri[256]; + GList *found; + + info = __create_control_info_from_bundle(b); + if (!info) + return NULL; + + b_info = *info; + + /* Step 1 */ + found = g_list_find_custom(__control_infos, &b_info, + __compare_control_infos); + if (found) { + __destroy_control_info(info); + return found->data; + } + + /* Step 2 */ + if (strcmp(b_info.uri_scheme, "NULL") != 0 && + strcmp(b_info.uri_host, "NULL") != 0) { + snprintf(uri, sizeof(uri), "%s://%s", + b_info.uri_scheme, b_info.uri_host); + b_info.uri = uri; + found = g_list_find_custom(__control_infos, &b_info, + __compare_control_infos); + if (found) { + __destroy_control_info(info); + return found->data; + } + } + + /* Step 3 */ + b_info.uri = info->uri_scheme; + found = g_list_find_custom(__control_infos, &b_info, + __compare_control_infos); + if (found) { + __destroy_control_info(info); + return found->data; + } + + /* Step 4 */ + b_info.uri = "*"; + found = g_list_find_custom(__control_infos, &b_info, + __compare_control_infos); + if (found) { + __destroy_control_info(info); + return found->data; + } + + /* Step 5 */ + if (!strcmp(b_info.uri_scheme, "file") && + strcmp(b_info.mime, "NULL") != 0) { + b_info.uri = "NULL"; + found = g_list_find_custom(__control_infos, &b_info, + __compare_control_infos); + if (found) { + __destroy_control_info(info); + return found->data; + } + } + + __destroy_control_info(info); + + return NULL; +} + +static int __foreach_app_control_cb(const char *operation, + const char *uri, const char *mime, const char *id, + void *user_data) +{ + struct control_info_s *info; + + info = __create_control_info(id, operation, mime, uri); + if (!info) + return -1; + + __control_infos = g_list_append(__control_infos, info); + + return 0; +} + +int appcore_base_control_init(void) +{ + pkgmgrinfo_appinfo_h handle; + char appid[512]; + int r; + + if (__control_info_initialized) + return APPCORE_BASE_ERROR_NONE; + + r = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)); + if (r != AUL_R_OK) { + _ERR("Failed to get application ID. result(%x)", r); + return APPCORE_BASE_ERROR_IO_ERROR; + } + + r = pkgmgrinfo_appinfo_get_appinfo(appid, &handle); + if (r != PMINFO_R_OK) { + _ERR("Failed to get app info. result(%x)", r); + return APPCORE_BASE_ERROR_IO_ERROR; + } + + r = pkgmgrinfo_appinfo_foreach_appcontrol_v2(handle, + __foreach_app_control_cb, NULL); + if (r != PMINFO_R_OK) { + _ERR("Failed to retrieve app-control. result(%x)", r); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + return APPCORE_BASE_ERROR_IO_ERROR; + } + + pkgmgrinfo_appinfo_destroy_appinfo(handle); + + __control_info_initialized = true; + + return APPCORE_BASE_ERROR_NONE; +} + +void appcore_base_control_fini(void) +{ + if (__controls) { + g_list_free_full(__controls, + (GDestroyNotify)appcore_base_control_remove); + __controls = NULL; + } + + if (__control_infos) { + g_list_free_full(__control_infos, __destroy_control_info); + __control_infos = NULL; + } + + __control_info_initialized = false; +} + +int appcore_base_control_invoke(bundle *b) +{ + struct appcore_base_control_s *ctrl; + struct control_info_s *info; + GList *iter; + + if (!b) { + _ERR("Invalid parameter"); + return APPCORE_BASE_ERROR_INVALID_PARAMETER; + } + + if (!__controls) + return APPCORE_BASE_ERROR_NONE; + + info = __find_control_info(b); + if (!info) + return APPCORE_BASE_ERROR_NONE; + + iter = __controls; + while (iter) { + ctrl = (struct appcore_base_control_s *)iter->data; + if (!strcmp(ctrl->id, info->id)) + ctrl->callback(b, ctrl->user_data); + + iter = g_list_next(iter); + } + + _DBG("[app-control] id(%s)", info->id); + return APPCORE_BASE_ERROR_NONE; +} + +static bool __control_info_exists(const char *id) +{ + struct control_info_s *info; + GList *iter; + + iter = __control_infos; + while (iter) { + info = (struct control_info_s *)iter->data; + if (!strcmp(info->id, id)) + return true; + + iter = g_list_next(iter); + } + + return false; +} + +EXPORT_API int appcore_base_control_add(const char *id, + appcore_base_control_cb callback, void *user_data, + appcore_base_control_h *h) +{ + struct appcore_base_control_s *ctrl; + int r; + + if (!id || !callback || !h) { + _ERR("Invalid parameter"); + return APPCORE_BASE_ERROR_INVALID_PARAMETER; + } + + r = appcore_base_control_init(); + if (r < 0) { + _ERR("Failed to initialize app-control info"); + return r; + } + + if (!__control_info_exists(id)) { + _ERR("Failed to find control info(%s)", id); + return APPCORE_BASE_ERROR_KEY_NOT_FOUND; + } + + ctrl = calloc(1, sizeof(struct appcore_base_control_s)); + if (!ctrl) { + _ERR("Out of memory"); + return APPCORE_BASE_ERROR_OUT_OF_MEMORY; + } + + ctrl->id = strdup(id); + if (!ctrl->id) { + _ERR("Failed to duplicate app-control ID"); + free(ctrl); + return APPCORE_BASE_ERROR_OUT_OF_MEMORY; + } + + ctrl->callback = callback; + ctrl->user_data = user_data; + + __controls = g_list_append(__controls, ctrl); + + *h = ctrl; + + return APPCORE_BASE_ERROR_NONE; +} + +EXPORT_API int appcore_base_control_remove(appcore_base_control_h h) +{ + struct appcore_base_control_s *ctrl; + + if (!h || !g_list_find(__controls, h)) { + _ERR("Invalid parameter"); + return APPCORE_BASE_ERROR_INVALID_PARAMETER; + } + + ctrl = (struct appcore_base_control_s *)h; + __controls = g_list_remove(__controls, ctrl); + + if (ctrl->id) + free(ctrl->id); + free(ctrl); + + return APPCORE_BASE_ERROR_NONE; +} -- 2.7.4