Support handling of each app-control ID 04/199104/16
authorHwankyu Jhun <h.jhun@samsung.com>
Sun, 3 Feb 2019 09:39:40 +0000 (18:39 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 18 Feb 2019 12:37:29 +0000 (21:37 +0900)
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 <h.jhun@samsung.com>
CMakeLists.txt
include/appcore_base.h
include/appcore_base_control.h [new file with mode: 0644]
packaging/app-core.spec
src/base/appcore_base.c
src/base/appcore_base_control.c [new file with mode: 0644]

index 17f4d5b..a85c605 100644 (file)
@@ -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")
index 4d4ccea..760cade 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdbool.h>
 #include <libintl.h>
+#include <errno.h>
 #include <bundle.h>
 #include <aul.h>
 
@@ -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 (file)
index 0000000..ffc6832
--- /dev/null
@@ -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 <bundle.h>
+
+#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);
index 2e34380..5770ce1 100644 (file)
@@ -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
index 27eee21..e276926 100644 (file)
@@ -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 (file)
index 0000000..b096417
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <linux/limits.h>
+#include <glib.h>
+#include <bundle_internal.h>
+#include <pkgmgr-info.h>
+#include <aul_svc.h>
+#include <aul_svc_internal.h>
+
+#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;
+}