Add app_info_foreach_category CAPI 70/123570/9
authorJunghyun Yeon <jungh.yeon@samsung.com>
Thu, 6 Apr 2017 06:30:09 +0000 (15:30 +0900)
committerJunghyun Yeon <jungh.yeon@samsung.com>
Wed, 12 Apr 2017 07:51:28 +0000 (16:51 +0900)
Change-Id: Ib06b7a0ea63793e65344f4ae4dff22605c69ec17
Signed-off-by: Junghyun Yeon <jungh.yeon@samsung.com>
include/app_info.h
src/app_info.c
src/app_manager_internal.h

index 14c65c1..8125341 100644 (file)
@@ -114,6 +114,20 @@ typedef bool (*app_info_filter_cb) (app_info_h app_info, void *user_data);
 typedef bool (*app_info_metadata_cb) (const char *metadata_key, const char *metadata_value, void *user_data);
 
 /**
+ * @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  Creates the application information handle.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in]   app_id    The application ID
@@ -336,6 +350,24 @@ int app_info_is_preload(app_info_h app_info, bool *preload);
 int app_info_clone(app_info_h *clone, app_info_h app_info);
 
 /**
+ * @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);
+
+/**
  * @brief  Creates the application information filter handle from DB.
  *         All filter properties will be ANDed.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
index a70407a..c9967ec 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include <pkgmgr-info.h>
 #include <package-manager.h>
 #include <dlog.h>
+#include <cynara-client.h>
 
 #include "app_info.h"
 #include "app_manager.h"
@@ -34,6 +36,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 +61,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 +94,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 +166,21 @@ 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_app_info_cb(pkgmgrinfo_appinfo_h handle, void *cb_data)
 {
        foreach_context_s *foreach_context = cb_data;
@@ -211,6 +234,64 @@ int app_info_foreach_app_info(app_manager_app_info_cb callback, void *user_data)
        return APP_MANAGER_ERROR_NONE;
 }
 
+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;
+}
+
 API int app_info_create(const char *app_id, app_info_h *app_info)
 {
        pkgmgrinfo_pkginfo_h pkginfo = NULL;
@@ -552,6 +633,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;
index 7a6100e..dd76ef8 100644 (file)
@@ -27,6 +27,8 @@
 #define API __attribute__ ((visibility("default")))
 #endif
 
+#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);