From dda7f99a0e7b68acbf57afa9149e09eeb55a7f38 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 6 Apr 2017 16:32:31 +0900 Subject: [PATCH] Add app_info_foreach_category as extension API Change-Id: I08dceff8defc490be39979516fb9d439048e055d Signed-off-by: Junghyun Yeon --- include/app_info_extension.h | 74 ++++++++++++++++++ src/app_info.c | 143 ++++++++++++++++++++++++++++++++++- src/app_manager_internal.h | 2 + 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 include/app_info_extension.h diff --git a/include/app_info_extension.h b/include/app_info_extension.h new file mode 100644 index 0000000..ccf922b --- /dev/null +++ b/include/app_info_extension.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 - 2017 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. + */ + +#ifndef __TIZEN_APPFW_APP_INFO_EXTENSION_H +#define __TIZEN_APPFW_APP_INFO_EXTENSION_H + +#include + +#include "app_info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file app_info_extension.h + */ + +/** + * @addtogroup CAPI_APPLICATION_INFO_MODULE + * @{ + */ + +/** + * @brief Called for each application category in app_info_foreach_category(). + * @since_tizen 4.0 + * @remarks @a category will be freed when the application information handle is destroyed + * using app_info_destroy() + * @param[in] category The name of the category + * @param[in] user_data The user data passed to app_info_foreach_category() + * @return @c true to continue with the next iteration of the loop, \n + * otherwise @c false to break out of the loop + * @pre app_info_foreach_category() will invoke this callback. + * @see app_info_foreach_category() + */ +typedef bool (*app_info_category_cb) (const char *category, void *user_data); + +/** + * @brief Runs a callback for each category which the given application belongs to. + * @since_tizen 4.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] app_info The application information + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #APP_MANAGER_ERROR_NONE Successful + * @retval #APP_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #APP_MANAGER_ERROR_IO_ERROR I/O error + * @retval #APP_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @see app_info_create() + */ +int app_info_foreach_category(app_info_h app_info, app_info_category_cb callback, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_APPFW_APP_INFO_EXTENSION_H */ + diff --git a/src/app_info.c b/src/app_info.c index a70407a..f23e44e 100644 --- a/src/app_info.c +++ b/src/app_info.c @@ -19,12 +19,15 @@ #include #include #include +#include #include #include #include +#include #include "app_info.h" +#include "app_info_extension.h" #include "app_manager.h" #include "app_manager_internal.h" @@ -34,6 +37,8 @@ #define LOG_TAG "TIZEN_N_APP_MANAGER" +#define SMACK_LABEL_LEN 255 + struct app_info_s { char *app_id; pkgmgrinfo_appinfo_h pkg_app_info; @@ -57,6 +62,11 @@ typedef struct _foreach_metada_context_ { void *user_data; } foreach_metadata_context_s; +typedef struct _foreach_category_ { + app_info_category_cb callback; + void *user_data; +} foreach_category_context_s; + static int app_info_convert_str_property(const char *property, char **converted_property) { if (property == NULL) @@ -85,7 +95,6 @@ static int app_info_convert_bool_property(const char *property, char **converted *converted_property = PMINFO_APPINFO_PROP_APP_NODISPLAY; else if (strcmp(property, PACKAGE_INFO_PROP_APP_TASKMANAGE) == 0) *converted_property = PMINFO_APPINFO_PROP_APP_TASKMANAGE; - else return -1; @@ -158,6 +167,36 @@ static int app_info_foreach_app_metadata_cb(const char *metadata_key, const char return PMINFO_R_ERROR; } +static int app_info_foreach_caregory_cb(const char *category_name, void *user_data) +{ + foreach_category_context_s *foreach_category = user_data; + bool iteration_next = true; + + if (category_name == NULL || foreach_category == NULL) + return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + + iteration_next = foreach_category->callback(category_name, foreach_category->user_data); + if (iteration_next == true) + return PMINFO_R_OK; + else + return PMINFO_R_ERROR; +} + +static int app_info_foreach_caregory_cb(const char *category_name, void *user_data) +{ + foreach_category_context_s *foreach_category = user_data; + bool iteration_next = true; + + if (category_name == NULL || foreach_category == NULL) + return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + + iteration_next = foreach_category->callback(category_name, foreach_category->user_data); + if (iteration_next == true) + return PMINFO_R_OK; + else + return PMINFO_R_ERROR; +} + static int app_info_foreach_app_info_cb(pkgmgrinfo_appinfo_h handle, void *cb_data) { foreach_context_s *foreach_context = cb_data; @@ -196,6 +235,64 @@ static int app_info_foreach_app_info_cb(pkgmgrinfo_appinfo_h handle, void *cb_da return PMINFO_R_ERROR; } +static int _check_privilege(char *privilege) +{ + cynara *p_cynara; + int fd; + int ret; + + char client[SMACK_LABEL_LEN + 1] = ""; + char uid[10] = {0,}; + char *client_session = ""; + + if (privilege == NULL) { + LOGE("invalid parameter"); + return APP_MANAGER_ERROR_INVALID_PARAMETER; + } + + ret = cynara_initialize(&p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + LOGE("cynara_initialize [%d] failed!", ret); + return APP_MANAGER_ERROR_IO_ERROR; + } + + fd = open("/proc/self/attr/current", O_RDONLY); + if (fd < 0) { + LOGE("open [%d] failed!", errno); + ret = APP_MANAGER_ERROR_IO_ERROR; + goto out; + } + + ret = read(fd, client, SMACK_LABEL_LEN); + if (ret < 0) { + LOGE("read [%d] failed!", errno); + close(fd); + ret = APP_MANAGER_ERROR_IO_ERROR; + goto out; + } + close(fd); + snprintf(uid, 10, "%d", getuid()); + + ret = cynara_check(p_cynara, client, client_session, uid, privilege); + if (ret != CYNARA_API_ACCESS_ALLOWED) { + LOGE("cynara access check [%d] failed!", ret); + + if (ret == CYNARA_API_ACCESS_DENIED) + ret = APP_MANAGER_ERROR_PERMISSION_DENIED; + else + ret = APP_MANAGER_ERROR_IO_ERROR; + + goto out; + } + ret = APP_MANAGER_ERROR_NONE; + +out: + if (p_cynara) + cynara_finish(p_cynara); + + return ret; +} + int app_info_foreach_app_info(app_manager_app_info_cb callback, void *user_data) { foreach_context_s foreach_context = { @@ -552,6 +649,28 @@ API int app_info_clone(app_info_h *clone, app_info_h app_info) return APP_MANAGER_ERROR_NONE; } +API int app_info_foreach_category(app_info_h app_info, app_info_category_cb callback, void *user_data) +{ + int retval; + if (app_info == NULL || callback == NULL) + return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + retval = _check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != APP_MANAGER_ERROR_NONE) + return app_manager_error(APP_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); + + foreach_category_context_s foreach_category = { + .callback = callback, + .user_data = user_data, + }; + + retval = pkgmgrinfo_appinfo_foreach_category(app_info->pkg_app_info, app_info_foreach_caregory_cb, &foreach_category); + if (retval != PMINFO_R_OK) + return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + + return APP_MANAGER_ERROR_NONE; +} + API int app_info_filter_create(app_info_filter_h *handle) { int retval = 0; @@ -664,6 +783,28 @@ API int app_info_filter_foreach_appinfo(app_info_filter_h handle, app_info_filte return APP_MANAGER_ERROR_NONE; } +API int app_info_foreach_category(app_info_h app_info, app_info_category_cb callback, void *user_data) +{ + int retval; + if (app_info == NULL || callback == NULL) + return app_manager_error(APP_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + retval = _check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != APP_MANAGER_ERROR_NONE) + return app_manager_error(APP_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); + + foreach_category_context_s foreach_category = { + .callback = callback, + .user_data = user_data, + }; + + retval = pkgmgrinfo_appinfo_foreach_category(app_info->pkg_app_info, app_info_foreach_caregory_cb, &foreach_category); + if (retval != PMINFO_R_OK) + return app_manager_error(APP_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + + return APP_MANAGER_ERROR_NONE; +} + API int app_info_metadata_filter_create(app_info_metadata_filter_h *handle) { int retval = 0; diff --git a/src/app_manager_internal.h b/src/app_manager_internal.h index 5185e23..3aae00e 100644 --- a/src/app_manager_internal.h +++ b/src/app_manager_internal.h @@ -38,6 +38,8 @@ extern "C" { * @{ */ +#define PRIVILEGE_PACKAGE_MANAGER_ADMIN "http://tizen.org/privilege/packagemanager.admin" + int app_manager_error(app_manager_error_e error, const char *function, const char *description); int app_context_foreach_app_context(app_manager_app_context_cb callback, void *user_data); -- 2.34.1