From f3e351be4cc507bc954f81e709c697c55793cd5b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 17 Mar 2021 14:52:55 +0900 Subject: [PATCH] Refactor AppControl API Change-Id: I4b2270c3aac3663da9b21165d4bea765f9ef7bc7 Signed-off-by: Hwankyu Jhun --- include/app_control.h | 4 +- include/app_control_internal.h | 10 +- src/app-control/CMakeLists.txt | 2 + src/app-control/app_control.c | 2505 ----------------------- src/app-control/app_control.cc | 458 +++++ src/app-control/app_control.hh | 116 ++ src/app-control/app_control_action.cc | 60 + src/app-control/app_control_action.hh | 50 + src/app-control/app_control_broker.cc | 410 ++++ src/app-control/app_control_broker.hh | 84 + src/app-control/error.hh | 41 + src/app-control/exception.hh | 55 + src/app-control/launch_mode.hh | 29 + src/app-control/log_private.hh | 37 + src/app-control/pending_item.cc | 78 + src/app-control/pending_item.hh | 73 + src/app-control/request_context.cc | 61 + src/app-control/request_context.hh | 51 + src/app-control/result.hh | 31 + src/app-control/stub.cc | 1215 +++++++++++ src/app-control/util.cc | 71 + src/app-control/util.hh | 39 + test/unit_tests/app_control_unittest.cc | 12 +- test/unit_tests/mock/aul_mock.cc | 7 +- test/unit_tests/mock/aul_mock.hh | 4 +- 25 files changed, 2983 insertions(+), 2520 deletions(-) delete mode 100644 src/app-control/app_control.c create mode 100644 src/app-control/app_control.cc create mode 100644 src/app-control/app_control.hh create mode 100644 src/app-control/app_control_action.cc create mode 100644 src/app-control/app_control_action.hh create mode 100644 src/app-control/app_control_broker.cc create mode 100644 src/app-control/app_control_broker.hh create mode 100644 src/app-control/error.hh create mode 100644 src/app-control/exception.hh create mode 100644 src/app-control/launch_mode.hh create mode 100644 src/app-control/log_private.hh create mode 100644 src/app-control/pending_item.cc create mode 100644 src/app-control/pending_item.hh create mode 100644 src/app-control/request_context.cc create mode 100644 src/app-control/request_context.hh create mode 100644 src/app-control/result.hh create mode 100644 src/app-control/stub.cc create mode 100644 src/app-control/util.cc create mode 100644 src/app-control/util.hh diff --git a/include/app_control.h b/include/app_control.h index b9ecae6..2600f0a 100644 --- a/include/app_control.h +++ b/include/app_control.h @@ -39,7 +39,7 @@ extern "C" { * @brief The application control handle. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ -typedef struct app_control_s *app_control_h; +typedef void *app_control_h; /** @@ -738,7 +738,7 @@ typedef void (*app_control_result_cb)(app_control_h request, app_control_error_e * @brief The application control action handle. * @since_tizen 5.5 */ -typedef struct app_control_action_s *app_control_action_h; +typedef void *app_control_action_h; /** * @brief Called when another application sends a launch request to the application. diff --git a/include/app_control_internal.h b/include/app_control_internal.h index 60c6b7a..5a959e0 100644 --- a/include/app_control_internal.h +++ b/include/app_control_internal.h @@ -34,6 +34,10 @@ extern "C" { * @{ */ +#ifndef DEPRECATED_API +#define DEPRECATED_API __attribute__((__visibility__("default"), deprecated)) +#endif + /** * @brief Definition for the app_control data: Connects the previous application with the next application when the sub-application is terminated. * @details If a sub-application is terminated, the framework will connect the previous application with the next application. @@ -149,7 +153,7 @@ int app_control_to_bundle(app_control_h app_control, bundle **data); * @retval #APP_CONTROL_ERROR_OUT_OF_MEMORY Out of memory * @see app_control_get_window() */ -int app_control_set_window(app_control_h app_control, unsigned int id); +int app_control_set_window(app_control_h app_control, unsigned int id) DEPRECATED_API; /** * @brief Gets the window ID of the application. @@ -164,7 +168,7 @@ int app_control_set_window(app_control_h app_control, unsigned int id); * @retval #APP_CONTROL_ERROR_OUT_OF_MEMORY Out of memory * @see app_control_set_app_id() */ -int app_control_get_window(app_control_h app_control, unsigned int *id); +int app_control_get_window(app_control_h app_control, unsigned int *id) DEPRECATED_API; typedef int (*app_control_host_res_fn)(void *data); @@ -182,7 +186,7 @@ typedef int (*app_control_host_res_fn)(void *data); * @retval #APP_CONTROL_ERROR_NONE Successful * @retval #APP_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter */ -int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data); +int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data) DEPRECATED_API; /** * @platform diff --git a/src/app-control/CMakeLists.txt b/src/app-control/CMakeLists.txt index b478318..61b25b0 100644 --- a/src/app-control/CMakeLists.txt +++ b/src/app-control/CMakeLists.txt @@ -5,7 +5,9 @@ SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL} PROPERTIES VERSION ${FULLVER}) TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CONTROL} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../../include) APPLY_PKG_CONFIG(${TARGET_APP_CONTROL} PUBLIC diff --git a/src/app-control/app_control.c b/src/app-control/app_control.c deleted file mode 100644 index 657a109..0000000 --- a/src/app-control/app_control.c +++ /dev/null @@ -1,2505 +0,0 @@ -/* - * Copyright (c) 2011 - 2016 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. - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "CAPI_APPFW_APP_CONTROL" - -#ifndef TIZEN_PATH_MAX -#define TIZEN_PATH_MAX 1024 -#endif - -#define BUNDLE_KEY_PREFIX_AUL "__AUL_" -#define BUNDLE_KEY_PREFIX_SERVICE "__APP_SVC_" - -#define BUNDLE_KEY_OPERATION "__APP_SVC_OP_TYPE__" -#define BUNDLE_KEY_URI "__APP_SVC_URI__" -#define BUNDLE_KEY_MIME "__APP_SVC_MIME_TYPE__" -#define BUNDLE_KEY_DATA "__APP_SVC_DATA__" -#define BUNDLE_KEY_PACKAGE "__APP_SVC_PKG_NAME__" -#define BUNDLE_KEY_WINDOW "__APP_SVC_K_WIN_ID__" -#define BUNDLE_KEY_CATEGORY "__APP_SVC_CATEGORY__" - -#define LAUNCH_MODE_SIZE 8 -#define LAUNCH_MODE_SINGLE "single" -#define LAUNCH_MODE_GROUP "group" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -#undef EXPORT_API -#define EXPORT_API __attribute__ ((visibility("default"))) - -typedef enum { - APP_CONTROL_TYPE_REQUEST, - APP_CONTROL_TYPE_EVENT, - APP_CONTROL_TYPE_REPLY, -} app_control_type_e; - -struct app_control_s { - int id; - app_control_type_e type; - bundle *data; - int launch_pid; -}; - -typedef struct app_control_request_context_s { - app_control_h app_control; - app_control_result_cb result_cb; - app_control_reply_cb reply_cb; - void *user_data; -} *app_control_request_context_h; - -struct launch_request_s { - int id; - bool implicit_default_operation; - app_control_request_context_h request_context; - app_control_h app_control; - app_control_result_cb result_cb; - app_control_reply_cb reply_cb; - void *user_data; - app_control_h reply; - app_control_result_e result; -}; - -struct app_control_action_s { - char *action; - appcore_base_control_h handle; - app_control_action_cb callback; - void *user_data; -}; - -struct reply_info_s { - bundle *b; - aul_svc_result_val result; - void *user_data; -}; - -struct result_info_s { - int result; - void *user_data; -}; - -struct pending_item_s { - int id; - struct reply_info_s *reply_info; - struct result_info_s *result_info; -}; - -typedef int (*launch_request_handler)(struct launch_request_s *req); - -static int app_control_create_reply(bundle *data, struct app_control_s **app_control); -static void app_control_request_reply_broker(bundle *appsvc_bundle, - int appsvc_request_code, aul_svc_result_val appsvc_result, - void *appsvc_data); -static void app_control_request_result_broker(int request_code, int result, - void *user_data); - -static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER; -static GList *__pending_list; - -static int __generate_request_id(void) -{ - static int id; - - g_atomic_int_inc(&id); - return id; -} - -static void __destroy_result_info(gpointer data) -{ - struct result_info_s *info = data; - - if (!info) - return; - - free(info); -} - -static struct result_info_s *__create_result_info(int result, - void *user_data) -{ - struct result_info_s *info; - - info = calloc(1, sizeof(struct result_info_s)); - if (!info) { - LOGE("Out of memory"); - return NULL; - } - - info->result = result; - info->user_data = user_data; - - return info; -} - -static void __destroy_reply_info(gpointer data) -{ - struct reply_info_s *info = data; - - if (!info) - return; - - if (info->b) - bundle_free(info->b); - - free(info); -} - -static struct reply_info_s *__create_reply_info(bundle *b, - aul_svc_result_val result, void *user_data) -{ - struct reply_info_s *info; - - info = calloc(1, sizeof(struct reply_info_s)); - if (!info) { - LOGE("Out of memory"); - return NULL; - } - - info->b = bundle_dup(b); - if (!info->b) { - LOGE("Failed to duplicate bundle"); - free(info); - return NULL; - } - - info->result = result; - info->user_data = user_data; - - return info; -} - -static void __destroy_pending_item(gpointer data) -{ - struct pending_item_s *item = data; - - if (!item) - return; - - if (item->reply_info) - __destroy_reply_info(item->reply_info); - - if (item->result_info) - __destroy_result_info(item->result_info); - - free(item); -} - -static struct pending_item_s *__create_pending_item(int id) -{ - struct pending_item_s *item; - - item = calloc(1, sizeof(struct pending_item_s)); - if (!item) { - LOGE("Out of memory"); - return NULL; - } - - item->id = id; - - return item; -} - -static void __add_pending_item(int id) -{ - struct pending_item_s *item; - - item = __create_pending_item(id); - if (!item) - return; - - pthread_mutex_lock(&__mutex); - __pending_list = g_list_prepend(__pending_list, item); - pthread_mutex_unlock(&__mutex); -} - -static void __remove_pending_item(int id) -{ - struct pending_item_s *item; - GList *iter; - - pthread_mutex_lock(&__mutex); - iter = __pending_list; - while (iter) { - item = (struct pending_item_s *)iter->data; - iter = g_list_next(iter); - if (item->id == id) { - __pending_list = g_list_remove(__pending_list, item); - __destroy_pending_item(item); - break; - } - } - pthread_mutex_unlock(&__mutex); -} - -static struct pending_item_s *__pop_pending_item(int id) -{ - struct pending_item_s *item; - GList *iter; - - pthread_mutex_lock(&__mutex); - iter = __pending_list; - while (iter) { - item = (struct pending_item_s *)iter->data; - iter = g_list_next(iter); - if (item->id == id) { - __pending_list = g_list_remove(__pending_list, item); - pthread_mutex_unlock(&__mutex); - return item; - } - } - pthread_mutex_unlock(&__mutex); - - return NULL; -} - -static gboolean __process_pending_item(gpointer data) -{ - struct pending_item_s *item = data; - struct result_info_s *result_info; - struct reply_info_s *reply_info; - - if (!item) - return G_SOURCE_REMOVE; - - if (item->result_info) { - result_info = item->result_info; - app_control_request_result_broker(item->id, - result_info->result, result_info->user_data); - __destroy_result_info(result_info); - item->result_info = NULL; - return G_SOURCE_CONTINUE; - } - - if (item->reply_info) { - reply_info = item->reply_info; - app_control_request_reply_broker(reply_info->b, item->id, - reply_info->result, reply_info->user_data); - __destroy_reply_info(reply_info); - item->reply_info = NULL; - } - __destroy_pending_item(item); - - return G_SOURCE_REMOVE; -} - -static void __flush_pending_item(int id) -{ - struct pending_item_s *item; - - item = __pop_pending_item(id); - if (!item) - return; - - if (!item->reply_info && !item->result_info) { - __destroy_pending_item(item); - return; - } - - g_idle_add(__process_pending_item, item); -} - -static bool __exist_pending_item(int id) -{ - struct pending_item_s *item; - GList *iter; - - pthread_mutex_lock(&__mutex); - iter = __pending_list; - while (iter) { - item = (struct pending_item_s *)iter->data; - iter = g_list_next(iter); - if (item->id == id) { - pthread_mutex_unlock(&__mutex); - return true; - } - } - pthread_mutex_unlock(&__mutex); - - return false; -} - -static int __pending_item_set_reply_info(int id, struct reply_info_s *info) -{ - struct pending_item_s *item; - GList *iter; - - pthread_mutex_lock(&__mutex); - iter = __pending_list; - while (iter) { - item = (struct pending_item_s *)iter->data; - iter = g_list_next(iter); - if (item->id == id) { - item->reply_info = info; - pthread_mutex_unlock(&__mutex); - return 0; - } - } - pthread_mutex_unlock(&__mutex); - - return -1; -} - -static int __pending_item_set_result_info(int id, struct result_info_s *info) -{ - struct pending_item_s *item; - GList *iter; - - pthread_mutex_lock(&__mutex); - iter = __pending_list; - while (iter) { - item = (struct pending_item_s *)iter->data; - iter = g_list_next(iter); - if (item->id == id) { - item->result_info = info; - pthread_mutex_unlock(&__mutex); - return 0; - } - } - pthread_mutex_unlock(&__mutex); - - return -1; -} - -static const char *app_control_error_to_string(app_control_error_e error) -{ - switch (error) { - case APP_CONTROL_ERROR_NONE: - return "NONE"; - case APP_CONTROL_ERROR_INVALID_PARAMETER: - return "INVALID_PARAMETER"; - case APP_CONTROL_ERROR_OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; - case APP_CONTROL_ERROR_APP_NOT_FOUND: - return "APP_NOT_FOUND"; - case APP_CONTROL_ERROR_KEY_NOT_FOUND: - return "KEY_NOT_FOUND"; - case APP_CONTROL_ERROR_KEY_REJECTED: - return "KEY_REJECTED"; - case APP_CONTROL_ERROR_INVALID_DATA_TYPE: - return "INVALID_DATA_TYPE"; - case APP_CONTROL_ERROR_LAUNCH_REJECTED: - return "LAUNCH_REJECTED"; - case APP_CONTROL_ERROR_PERMISSION_DENIED: - return "PERMISSION_DENIED"; - case APP_CONTROL_ERROR_LAUNCH_FAILED: - return "LAUNCH_FAILED"; - case APP_CONTROL_ERROR_TIMED_OUT: - return "TIMED_OUT"; - case APP_CONTROL_ERROR_IO_ERROR: - return "IO ERROR"; - default: - return "UNKNOWN"; - } -} - -static int app_control_error(app_control_error_e error, const char *function, const char *description) -{ - if (description) - LOGE("[%s] %s(0x%08x) : %s", function, app_control_error_to_string(error), error, description); - else { - if (error == APP_CONTROL_ERROR_KEY_NOT_FOUND) - LOGW("[%s] %s(0x%08x)", function, app_control_error_to_string(error), error); - else - LOGE("[%s] %s(0x%08x)", function, app_control_error_to_string(error), error); - } - - return error; -} - -static int app_control_validate_extra_data(const char *data) -{ - if (data == NULL || data[0] == '\0') - return APP_CONTROL_ERROR_INVALID_PARAMETER; - - return APP_CONTROL_ERROR_NONE; -} - -static int app_control_validate(app_control_h app_control) -{ - if (app_control == NULL || app_control->data == NULL) - return APP_CONTROL_ERROR_INVALID_PARAMETER; - - return APP_CONTROL_ERROR_NONE; -} - -static int app_control_new_id(void) -{ - static int sid; - - g_atomic_int_inc(&sid); - return sid; -} - -int app_control_validate_internal_key(const char *key) -{ - if (strncmp(BUNDLE_KEY_PREFIX_AUL, key, strlen(BUNDLE_KEY_PREFIX_AUL)) == 0) - return -1; - - if (strncmp(BUNDLE_KEY_PREFIX_SERVICE, key, strlen(BUNDLE_KEY_PREFIX_SERVICE)) == 0) - return -1; - - return 0; -} - -static app_control_result_e __get_app_control_result( - aul_svc_result_val appsvc_result) -{ - app_control_result_e result; - - switch (appsvc_result) { - case AUL_SVC_RES_OK: - result = APP_CONTROL_RESULT_SUCCEEDED; - break; - case AUL_SVC_RES_NOT_OK: - result = APP_CONTROL_RESULT_FAILED; - break; - case AUL_SVC_RES_CANCEL: - result = APP_CONTROL_RESULT_CANCELED; - break; - default: - result = APP_CONTROL_RESULT_CANCELED; - break; - } - - return result; -} - -/* LCOV_EXCL_START */ -static void app_control_request_reply_broker(bundle *appsvc_bundle, int appsvc_request_code, aul_svc_result_val appsvc_result, void *appsvc_data) -{ - app_control_request_context_h request_context; - app_control_h request; - app_control_h reply = NULL; - app_control_result_e result; - void *user_data; - app_control_reply_cb reply_cb; - struct reply_info_s *info; - int ret; - - if (appsvc_data == NULL) { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control reply"); - return; - } - - if (__exist_pending_item(appsvc_request_code)) { - info = __create_reply_info(appsvc_bundle, - appsvc_result, appsvc_data); - if (info) { - ret = __pending_item_set_reply_info(appsvc_request_code, - info); - if (ret == 0) { - LOGW("Reply info is pending"); - return; - } - __destroy_reply_info(info); - } - } - - if (app_control_create_reply(appsvc_bundle, &reply) != 0) { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create app_control reply"); - return; - } - - request_context = appsvc_data; - request = request_context->app_control; - result = __get_app_control_result(appsvc_result); - - user_data = request_context->user_data; - reply_cb = request_context->reply_cb; - - if (reply_cb != NULL) { - reply_cb(request, reply, result, user_data); - request_context->reply_cb = NULL; - } else { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback "); - } - - app_control_destroy(reply); - - if (request_context->result_cb) - return; - - if (request_context->app_control != NULL) - app_control_destroy(request_context->app_control); - - free(request_context); -} -/* LCOV_EXCL_STOP */ - -EXPORT_API int app_control_create_request(bundle *data, app_control_h *app_control) -{ - struct app_control_s *app_control_request; - - if (app_control == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - app_control_request = malloc(sizeof(struct app_control_s)); - if (app_control_request == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle"); - - app_control_request->type = APP_CONTROL_TYPE_REQUEST; - - if (data != NULL) - app_control_request->data = bundle_dup(data); - else - app_control_request->data = bundle_create(); - - if (app_control_request->data == NULL) { - free(app_control_request); - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a bundle"); - } - - app_control_request->id = app_control_new_id(); - app_control_request->launch_pid = -1; - - *app_control = app_control_request; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_create(app_control_h *app_control) -{ - return app_control_create_request(NULL, app_control); -} - -EXPORT_API int app_control_create_with_parameters(app_control_h *app_control, - const char *operation, const char *uri, const char *mime, - const char *category, const char *app_id, - app_control_launch_mode_e mode, int extra_data_count, ...) -{ - app_control_h tmp_control; - int ret; - va_list vl; - char *val; - char *key; - - if (app_control == NULL) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid prameter"); - } - - ret = app_control_create_request(NULL, &tmp_control); - if (ret != APP_CONTROL_ERROR_NONE) - return ret; - - ret = app_control_set_operation(tmp_control, operation); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_set_uri(tmp_control, uri); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_set_mime(tmp_control, mime); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_set_category(tmp_control, category); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_set_app_id(tmp_control, app_id); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_set_launch_mode(tmp_control, mode); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - va_start(vl, extra_data_count); - for (int i = 0; i < extra_data_count; i++) { - key = va_arg(vl, char *); - ret = app_control_validate_extra_data(key); - if (ret != APP_CONTROL_ERROR_NONE) { - va_end(vl); - app_control_destroy(tmp_control); - return ret; - } - - val = va_arg(vl, char *); - ret = app_control_validate_extra_data(val); - if (ret != APP_CONTROL_ERROR_NONE) { - va_end(vl); - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_add_extra_data(tmp_control, key, val); - if (ret != APP_CONTROL_ERROR_NONE) { - va_end(vl); - app_control_destroy(tmp_control); - return ret; - } - } - va_end(vl); - *app_control = tmp_control; - - return ret; -} - -static bool uri_query_cb(const char *key, const char *val, void *user_data) -{ - int ret; - - app_control_h *app_control = (app_control_h *)user_data; - - ret = app_control_add_extra_data(*app_control, key, val); - if (ret != APP_CONTROL_ERROR_NONE) { - LOGE("app_control_add_extra_data failed: %d[%s,%s]", ret, key, val); - return false; - } - - return true; -} - -EXPORT_API int app_control_create_from_uri_handle(app_control_h *app_control, - app_control_uri_h uri) -{ - app_control_h tmp_control; - const char *scheme; - const char *auth; - const char *path; - const char *fragment; - app_control_uri_query_h query; - char *uri_str; - int uri_str_len = 0; - int ret; - - if (app_control == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = app_control_create_request(NULL, &tmp_control); - if (ret != APP_CONTROL_ERROR_NONE) - return ret; - - ret = app_control_set_operation(tmp_control, - APP_CONTROL_OPERATION_INTENT); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_get_scheme(uri, &scheme); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_get_authority(uri, &auth); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_get_path(uri, &path); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_get_fragment(uri, &fragment); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_add_extra_data(tmp_control, - APP_CONTROL_DATA_URI_PATH, path); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_add_extra_data(tmp_control, - APP_CONTROL_DATA_URI_FRAGMENT, fragment); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_get_query(uri, &query); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - ret = app_control_uri_query_foreach(query, uri_query_cb, - &tmp_control); - if (ret != APP_CONTROL_ERROR_NONE) { - app_control_destroy(tmp_control); - return ret; - } - - uri_str_len = strlen(scheme) + strlen(auth) + 2; - uri_str = malloc(sizeof(char) * uri_str_len); - if (uri_str == NULL) { - app_control_destroy(tmp_control); - free(uri_str); - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } - - snprintf(uri_str, uri_str_len, "%s:%s", scheme, auth); - if (aul_svc_set_uri(tmp_control->data, uri_str) != 0) { - app_control_destroy(tmp_control); - free(uri_str); - return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, "invalid URI"); - } - - free(uri_str); - - *app_control = tmp_control; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_create_event(bundle *data, struct app_control_s **app_control) -{ - struct app_control_s *app_control_event; - - const char *operation; - - if (data == NULL || app_control == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - app_control_event = malloc(sizeof(struct app_control_s)); - if (app_control_event == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle"); - - app_control_event->type = APP_CONTROL_TYPE_EVENT; - app_control_event->data = bundle_dup(data); - if (app_control_event->data == NULL) { - free(app_control_event); - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to copy bundle data"); - } - - app_control_event->id = app_control_new_id(); - operation = aul_svc_get_operation(app_control_event->data); - if (operation == NULL) - aul_svc_set_operation(app_control_event->data, APP_CONTROL_OPERATION_DEFAULT); - - *app_control = app_control_event; - - return APP_CONTROL_ERROR_NONE; -} - -/* LCOV_EXCL_START */ -static int app_control_create_reply(bundle *data, struct app_control_s **app_control) -{ - struct app_control_s *app_control_reply; - - if (data == NULL || app_control == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - app_control_reply = malloc(sizeof(struct app_control_s)); - if (app_control_reply == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle"); - - app_control_reply->type = APP_CONTROL_TYPE_REPLY; - app_control_reply->data = bundle_dup(data); - app_control_reply->id = app_control_new_id(); - - *app_control = app_control_reply; - - return APP_CONTROL_ERROR_NONE; -} -/* LCOV_EXCL_STOP */ - -EXPORT_API int app_control_destroy(app_control_h app_control) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control->type == APP_CONTROL_TYPE_REQUEST && app_control->launch_pid > 0 - && bundle_get_val(app_control->data, AUL_SVC_K_LAUNCH_RESULT_APP_STARTED) == NULL) - aul_remove_caller_cb(app_control->launch_pid, app_control); - - bundle_free(app_control->data); - app_control->data = NULL; - free(app_control); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_to_bundle(app_control_h app_control, bundle **data) -{ - if (app_control_validate(app_control) || data == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - *data = app_control->data; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_operation(app_control_h app_control, const char *operation) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (operation != NULL) { - if (aul_svc_set_operation(app_control->data, operation) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid operation"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_OPERATION); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_operation(app_control_h app_control, char **operation) -{ - const char *operation_value; - - if (app_control_validate(app_control) || operation == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - operation_value = aul_svc_get_operation(app_control->data); - if (operation_value) { - *operation = strdup(operation_value); - if (*operation == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } else { - *operation = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_uri(app_control_h app_control, const char *uri) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (uri != NULL) { - if (aul_svc_set_uri(app_control->data, uri) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid URI"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_URI); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_uri(app_control_h app_control, char **uri) -{ - const char *uri_value; - - if (app_control_validate(app_control) || uri == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - uri_value = aul_svc_get_uri(app_control->data); - if (uri_value) { - *uri = strdup(uri_value); - if (*uri == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } else { - *uri = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_uri_by_handle(app_control_h app_control, app_control_uri_h uri) -{ - const char *scheme; - const char *auth; - char *uri_str; - int uri_str_len = 0; - - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_uri_get_scheme(uri, &scheme)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_uri_get_authority(uri, &auth)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - uri_str_len = strlen(scheme) + strlen(auth) + 2; - uri_str = malloc(sizeof(char) * uri_str_len); - if (uri_str == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - - snprintf(uri_str, uri_str_len, "%s:%s", scheme, auth); - if (aul_svc_set_uri(app_control->data, uri_str) != 0) { - free(uri_str); - return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, "invalid URI"); - } - - free(uri_str); - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_mime(app_control_h app_control, const char *mime) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (mime != NULL) { - if (aul_svc_set_mime(app_control->data, mime) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid MIME type"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_MIME); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_mime(app_control_h app_control, char **mime) -{ - const char *mime_value; - - if (app_control_validate(app_control) || mime == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - mime_value = aul_svc_get_mime(app_control->data); - if (mime_value) { - *mime = strdup(mime_value); - if (*mime == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } else { - *mime = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_category(app_control_h app_control, const char *category) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (category != NULL) { - if (aul_svc_set_category(app_control->data, category) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid Category"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_CATEGORY); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_category(app_control_h app_control, char **category) -{ - const char *category_value; - - if (app_control_validate(app_control) || category == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - category_value = aul_svc_get_category(app_control->data); - if (category_value) { - *category = strdup(category_value); - if (*category == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } else { - *category = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -int app_control_set_package(app_control_h app_control, const char *package) -{ - /* TODO: this function must be deprecated */ - return app_control_set_app_id(app_control, package); -} - -int app_control_get_package(app_control_h app_control, char **package) -{ - /* TODO: this function must be deprecated */ - return app_control_get_app_id(app_control, package); -} - -EXPORT_API int app_control_set_app_id(app_control_h app_control, const char *app_id) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_id != NULL) { - if (aul_svc_set_appid(app_control->data, app_id) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid application ID"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_PACKAGE); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_app_id(app_control_h app_control, char **app_id) -{ - const char *app_id_value; - - if (app_control_validate(app_control) || app_id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - app_id_value = aul_svc_get_appid(app_control->data); - if (app_id_value) { - *app_id = strdup(app_id_value); - if (*app_id == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - } else { - *app_id = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_window(app_control_h app_control, unsigned int id) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (id > 0) { - if (aul_svc_allow_transient_app(app_control->data, id) != 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid id"); - } else { - bundle_del(app_control->data, BUNDLE_KEY_WINDOW); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_window(app_control_h app_control, unsigned int *id) -{ - const char *window_id; - - if (app_control_validate(app_control) || id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - window_id = bundle_get_val(app_control->data, BUNDLE_KEY_WINDOW); - if (window_id != NULL) - *id = atoi(window_id); - else - *id = 0; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_clone(app_control_h *clone, app_control_h app_control) -{ - app_control_h app_control_clone; - - if (app_control_validate(app_control) || clone == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - app_control_clone = malloc(sizeof(struct app_control_s)); - if (app_control_clone == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a app_control handle"); - - app_control_clone->id = app_control_new_id(); - app_control_clone->type = app_control->type; - app_control_clone->data = bundle_dup(app_control->data); - app_control_clone->launch_pid = app_control->launch_pid; - - *clone = app_control_clone; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_launch_mode(app_control_h app_control, - app_control_launch_mode_e mode) -{ - char launch_mode[LAUNCH_MODE_SIZE] = { 0, }; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - } - - switch (mode) { - case APP_CONTROL_LAUNCH_MODE_SINGLE: - strncpy(launch_mode, LAUNCH_MODE_SINGLE, sizeof(launch_mode) - 1); - break; - case APP_CONTROL_LAUNCH_MODE_GROUP: - strncpy(launch_mode, LAUNCH_MODE_GROUP, sizeof(launch_mode) - 1); - break; - default: - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "invalid mode"); - } - - return aul_svc_set_launch_mode(app_control->data, launch_mode); -} - -EXPORT_API int app_control_get_launch_mode(app_control_h app_control, - app_control_launch_mode_e *mode) -{ - const char *launch_mode; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - } - - launch_mode = aul_svc_get_launch_mode(app_control->data); - if (launch_mode == NULL) { - *mode = APP_CONTROL_LAUNCH_MODE_SINGLE; - } else { - if (!strcmp(launch_mode, LAUNCH_MODE_SINGLE)) { - *mode = APP_CONTROL_LAUNCH_MODE_SINGLE; - } else if (!strcmp(launch_mode, LAUNCH_MODE_GROUP)) { - *mode = APP_CONTROL_LAUNCH_MODE_GROUP; - } else { - *mode = APP_CONTROL_LAUNCH_MODE_SINGLE; - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "launch_mode is not matched"); - } - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_defapp(app_control_h app_control, const char *app_id) -{ - int ret; - - if (app_control_validate(app_control) || app_id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = aul_svc_set_appid(app_control->data, app_id); - if (ret < 0) - return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL); - - ret = aul_set_default_app_by_operation(app_control->data); - if (ret < 0) { - if (ret == AUL_R_EILLACC) - return app_control_error(APP_CONTROL_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); - else - return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_unset_defapp(const char *app_id) -{ - int ret; - - if (app_id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = aul_unset_default_app_by_operation(app_id); - if (ret < 0) { - if (ret == AUL_R_EILLACC) - return app_control_error(APP_CONTROL_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); - else - return app_control_error(APP_CONTROL_ERROR_IO_ERROR, __FUNCTION__, NULL); - } - - return APP_CONTROL_ERROR_NONE; -} - -/* LCOV_EXCL_START */ -static void __update_launch_pid(int launched_pid, void *data) -{ - app_control_h app_control; - - if (data == NULL) - return; - - app_control = data; - - app_control->launch_pid = launched_pid; -} -/* LCOV_EXCL_STOP */ - -static void __handle_launch_result(int launched_pid, void *data) -{ - app_control_request_context_h request_context; - app_control_h reply = NULL; - app_control_h request; - app_control_result_e result; - app_control_reply_cb reply_cb; - void *user_data; - char callee[255] = {0, }; - int ret; - - if (data == NULL) - return; - - request_context = (app_control_request_context_h)data; - - if (app_control_create_event(request_context->app_control->data, &reply) != 0) { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create app_control event"); - return; - } - - ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee)); - if (ret < 0) - LOGE("aul_app_get_appid_bypid failed: %d", launched_pid); - else - app_control_set_app_id(reply, callee); - - LOGI("app control async result callback callee pid:%d", launched_pid); - - result = APP_CONTROL_RESULT_APP_STARTED; - request = request_context->app_control; - user_data = request_context->user_data; - reply_cb = request_context->reply_cb; - - if (reply_cb != NULL) - reply_cb(request, reply, result, user_data); - else - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback "); - - app_control_destroy(reply); -} - -static app_control_error_e __launch_request_convert_error(int res) -{ - switch (res) { - case AUL_SVC_RET_OK: - return APP_CONTROL_ERROR_NONE; - case AUL_SVC_RET_ENOMATCH: - return APP_CONTROL_ERROR_APP_NOT_FOUND; - case AUL_SVC_RET_EILLACC: - return APP_CONTROL_ERROR_PERMISSION_DENIED; - case AUL_SVC_RET_EINVAL: - return APP_CONTROL_ERROR_INVALID_PARAMETER; - default: - return APP_CONTROL_ERROR_LAUNCH_REJECTED; - } -} - -static void __handle_app_started_result(app_control_h app_control, - app_control_request_context_h request_context) -{ - char callee[256] = { 0, }; - const char *str; - int ret; - - str = bundle_get_val(app_control->data, - AUL_SVC_K_LAUNCH_RESULT_APP_STARTED); - if (!str) { - aul_add_caller_cb(app_control->launch_pid, - __update_launch_pid, app_control); - return; - } - - ret = aul_app_get_appid_bypid(app_control->launch_pid, - callee, sizeof(callee)); - if (ret != AUL_R_OK) { - LOGE("Failed to get appliation ID. pid(%d)", - app_control->launch_pid); - } - - if (request_context && request_context->app_control) { - request_context->app_control->launch_pid = - app_control->launch_pid; - } - - aul_add_caller_cb(app_control->launch_pid, - __handle_launch_result, request_context); - - if (strcmp(callee, APP_SELECTOR) && - strcmp(callee, SHARE_PANEL)) - aul_invoke_caller_cb(request_context); -} - -static void app_control_request_result_broker(int request_code, int result, - void *user_data) -{ - app_control_request_context_h request_context; - app_control_error_e error = APP_CONTROL_ERROR_NONE; - app_control_h app_control; - struct result_info_s *info; - int ret; - - if (__exist_pending_item(request_code)) { - info = __create_result_info(result, user_data); - if (info) { - ret = __pending_item_set_result_info(request_code, - info); - if (ret == 0) { - LOGW("Result info is pending"); - return; - } - __destroy_result_info(info); - } - } - - request_context = (app_control_request_context_h)user_data; - if (request_context == NULL) { - LOGE("Invalid request"); - return; - } - - app_control = request_context->app_control; - app_control->launch_pid = result; - if (request_context->result_cb) { - if (result < 0) - error = __launch_request_convert_error(result); - request_context->result_cb(app_control, error, - request_context->user_data); - request_context->result_cb = NULL; - } - - if (result < 0 || !request_context->reply_cb) { - app_control_destroy(request_context->app_control); - free(request_context); - return; - } - - __handle_app_started_result(app_control, - request_context->reply_cb ? request_context : NULL); -} - -static int __launch_request_verify_operation(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - const char *operation; - const char *appid; - - operation = aul_svc_get_operation(app_control->data); - if (!operation) { - req->implicit_default_operation = true; - operation = APP_CONTROL_OPERATION_DEFAULT; - } - - if (!strcmp(operation, APP_CONTROL_OPERATION_LAUNCH_ON_EVENT)) { - return app_control_error(APP_CONTROL_ERROR_LAUNCH_REJECTED, - __FUNCTION__, "Not supported operation value"); - } - - if (!strcmp(operation, APP_CONTROL_OPERATION_DEFAULT)) { - appid = aul_svc_get_appid(app_control->data); - if (!appid) { - return app_control_error(APP_CONTROL_ERROR_APP_NOT_FOUND, - __FUNCTION__, - "Application ID must be specified"); - } - } - - return APP_CONTROL_ERROR_NONE; -} - -static int __launch_request_prepare_request_context(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - app_control_h request_clone; - int ret; - - if (!req->result_cb && !req->reply_cb) - return APP_CONTROL_ERROR_NONE; - - req->request_context = calloc(1, - sizeof(struct app_control_request_context_s)); - if (!req->request_context) { - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, "Ouf of memory"); - } - - ret = app_control_clone(&request_clone, app_control); - if (ret != APP_CONTROL_ERROR_NONE) { - return app_control_error(ret, __FUNCTION__, - "Failed to duplicate app control handle"); - } - - req->request_context->app_control = request_clone; - req->request_context->result_cb = req->result_cb; - req->request_context->reply_cb = req->reply_cb; - req->request_context->user_data = req->user_data; - - return APP_CONTROL_ERROR_NONE; -} - -static int __launch_request_send(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - aul_svc_res_fn reply_cb; - aul_svc_err_cb result_cb; - int ret; - - reply_cb = req->reply_cb ? app_control_request_reply_broker : NULL; - result_cb = req->result_cb ? app_control_request_result_broker : NULL; - - if (req->implicit_default_operation) { - aul_svc_set_operation(app_control->data, - APP_CONTROL_OPERATION_DEFAULT); - } - - if (req->request_context) - __add_pending_item(req->id); - - if (req->result_cb) { - ret = aul_svc_send_launch_request_for_uid(app_control->data, - req->id, reply_cb, result_cb, - req->request_context, getuid()); - } else { - ret = aul_svc_run_service_for_uid(app_control->data, - req->id, reply_cb, - req->request_context, getuid()); - } - - if (req->implicit_default_operation) - bundle_del(req->app_control->data, BUNDLE_KEY_OPERATION); - - if (ret < 0) { - if (req->request_context) - __remove_pending_item(req->id); - return app_control_error(__launch_request_convert_error(ret), - __FUNCTION__, NULL); - } - - app_control->launch_pid = ret; - - return APP_CONTROL_ERROR_NONE; -} - -static void __copy_callee_info(app_control_h dst, app_control_h src) -{ - const char *id; - - if (!dst || !src) - return; - - id = bundle_get_val(src->data, AUL_K_APPID); - if (id) { - bundle_del(dst->data, AUL_K_APPID); - bundle_add(dst->data, AUL_K_APPID, id); - } - - id = bundle_get_val(src->data, AUL_K_INSTANCE_ID); - if (id) { - bundle_del(dst->data, AUL_K_INSTANCE_ID); - bundle_add(dst->data, AUL_K_INSTANCE_ID, id); - } -} - -static int __launch_request_complete(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - app_control_request_context_h request_context = req->request_context; - - if (request_context) - __copy_callee_info(request_context->app_control, app_control); - - if (req->result_cb) { - __flush_pending_item(req->id); - return APP_CONTROL_ERROR_NONE; - } - - if (!request_context) - return APP_CONTROL_ERROR_NONE; - - __handle_app_started_result(app_control, - request_context->reply_cb ? request_context : NULL); - __flush_pending_item(req->id); - - return APP_CONTROL_ERROR_NONE; -} - -static int __send_launch_request(app_control_h app_control, - app_control_result_cb result_cb, - app_control_reply_cb reply_cb, - void *user_data) -{ - static launch_request_handler handlers[] = { - __launch_request_verify_operation, - __launch_request_prepare_request_context, - __launch_request_send, - __launch_request_complete, - }; - struct launch_request_s req = { - .implicit_default_operation = false, - .request_context = NULL, - .app_control = app_control, - .result_cb = result_cb, - .reply_cb = reply_cb, - .user_data = user_data, - .reply = NULL, - .result = APP_CONTROL_RESULT_FAILED, - }; - int ret; - int i; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - } - - req.id = __generate_request_id(); - for (i = 0; i < ARRAY_SIZE(handlers); i++) { - if (handlers[i]) { - ret = handlers[i](&req); - if (ret != APP_CONTROL_ERROR_NONE) - break; - } - } - - if (ret != APP_CONTROL_ERROR_NONE && req.request_context) { - if (req.request_context->app_control) - app_control_destroy(req.request_context->app_control); - - free(req.request_context); - } - - return ret; -} - -EXPORT_API int app_control_send_launch_request(app_control_h app_control, - app_control_reply_cb callback, void *user_data) -{ - int ret; - - ret = __send_launch_request(app_control, NULL, callback, user_data); - - return ret; -} - -EXPORT_API int app_control_send_terminate_request(app_control_h app_control) -{ - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control->type != APP_CONTROL_TYPE_REQUEST || app_control->launch_pid < 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - aul_svc_subapp_terminate_request(app_control->data, - app_control->launch_pid); - - return APP_CONTROL_ERROR_NONE; -} - -/* LCOV_EXCL_START */ -static bool app_control_copy_reply_data_cb(app_control_h app_control, const char *key, void *user_data) -{ - bundle *reply_data = user_data; - char *value = NULL; - char **value_array = NULL; - int value_array_length = 0; - int value_array_index = 0; - - if (reply_data == NULL) { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - return false; - } - - if (aul_svc_data_is_array(app_control->data, key)) { - app_control_get_extra_data_array(app_control, key, &value_array, &value_array_length); - aul_svc_add_data_array(reply_data, key, (const char **)value_array, value_array_length); - - for (value_array_index = 0; value_array_index < value_array_length; value_array_index++) - free(value_array[value_array_index]); - - free(value_array); - } else { - app_control_get_extra_data(app_control, key, &value); - aul_svc_add_data(reply_data, key, value); - free(value); - } - - return true; -} -/* LCOV_EXCL_STOP */ - -EXPORT_API int app_control_reply_to_launch_request(app_control_h reply, app_control_h request, app_control_result_e result) -{ - bundle *reply_data; - int appsvc_result; - int ret = 0; - - if (app_control_validate(reply) || app_control_validate(request)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (result == APP_CONTROL_RESULT_APP_STARTED) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "APP_CONTROL_RESULT_APP_STARTED is not allowed to use"); - - ret = aul_svc_create_result_bundle(request->data, &reply_data); - if (ret != 0) { - if (ret == AUL_SVC_RET_ECANCELED) - return APP_CONTROL_ERROR_NONE; - - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a result bundle"); - } - - app_control_foreach_extra_data(reply, app_control_copy_reply_data_cb, reply_data); - - switch (result) { - case APP_CONTROL_RESULT_SUCCEEDED: - appsvc_result = AUL_SVC_RES_OK; - break; - case APP_CONTROL_RESULT_FAILED: - appsvc_result = AUL_SVC_RES_NOT_OK; - break; - case APP_CONTROL_RESULT_CANCELED: - appsvc_result = AUL_SVC_RES_CANCEL; - break; - default: - appsvc_result = AUL_SVC_RES_CANCEL; - break; - } - - ret = aul_svc_send_result(reply_data, appsvc_result); - bundle_free(reply_data); - if (ret < 0) { - if (ret == AUL_SVC_RET_EINVAL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - else - return app_control_error(APP_CONTROL_ERROR_LAUNCH_REJECTED, __FUNCTION__, NULL); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_add_extra_data(app_control_h app_control, const char *key, const char *value) -{ - if (app_control_validate(app_control) || app_control_validate_extra_data(key) || app_control_validate_extra_data(value)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - if (aul_svc_get_data(app_control->data, key) != NULL) { - /* overwrite any existing value */ - bundle_del(app_control->data, key); - } - - if (aul_svc_add_data(app_control->data, key, value) != 0) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add data to the appsvc handle"); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_add_extra_data_array(app_control_h app_control, const char *key, const char* value[], int length) -{ - if (app_control_validate(app_control) || app_control_validate_extra_data(key)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (value == NULL || length <= 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid array"); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - if (aul_svc_get_data_array(app_control->data, key, NULL) != NULL) { - /* overwrite any existing value */ - bundle_del(app_control->data, key); - } - - if (aul_svc_add_data_array(app_control->data, key, value, length) != 0) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add array data to the appsvc handle"); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_remove_extra_data(app_control_h app_control, const char *key) -{ - if (app_control_validate(app_control) || app_control_validate_extra_data(key)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - if (bundle_del(app_control->data, key)) - return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_extra_data(app_control_h app_control, const char *key, char **value) -{ - const char *data_value; - - if (app_control_validate(app_control) || app_control_validate_extra_data(key) || value == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - data_value = aul_svc_get_data(app_control->data, key); - if (data_value == NULL) { - if (errno == ENOTSUP) - return app_control_error(APP_CONTROL_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL); - else - return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); - } - - *value = strdup(data_value); - if (*value == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_extra_data_array(app_control_h app_control, const char *key, char ***value, int *length) -{ - const char **array_data; - int array_data_length; - char **array_data_clone; - int i; - - if (app_control_validate(app_control) || app_control_validate_extra_data(key)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (value == NULL || length == 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - array_data = aul_svc_get_data_array(app_control->data, key, &array_data_length); - if (array_data == NULL) { - if (errno == ENOTSUP) - return app_control_error(APP_CONTROL_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL); - else - return app_control_error(APP_CONTROL_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); - } - - array_data_clone = calloc(array_data_length, sizeof(char *)); - if (array_data_clone == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - - for (i = 0; i < array_data_length; i++) { - if (array_data[i] != NULL) { - array_data_clone[i] = strdup(array_data[i]); - if (array_data_clone[i] == NULL) - goto error_oom; - } - } - - *value = array_data_clone; - *length = array_data_length; - - return APP_CONTROL_ERROR_NONE; - -error_oom: - for (i = 0; i < array_data_length; i++) { - if (array_data_clone[i]) - free(array_data_clone[i]); - } - free(array_data_clone); - - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); -} - -EXPORT_API int app_control_is_extra_data_array(app_control_h app_control, const char *key, bool *array) -{ - if (app_control_validate(app_control) || app_control_validate_extra_data(key) || array == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control_validate_internal_key(key)) - return app_control_error(APP_CONTROL_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); - - if (!aul_svc_data_is_array(app_control->data, key)) - *array = false; - else - *array = true; - - return APP_CONTROL_ERROR_NONE; -} - -typedef struct { - app_control_h app_control; - app_control_extra_data_cb callback; - void *user_data; - bool foreach_break; -} foreach_context_extra_data_t; - -static void app_control_cb_broker_bundle_iterator(const char *key, const int type, const bundle_keyval_t *kv, void *user_data) -{ - foreach_context_extra_data_t *foreach_context = NULL; - app_control_extra_data_cb extra_data_cb; - - if (key == NULL || !(type == BUNDLE_TYPE_STR || type == BUNDLE_TYPE_STR_ARRAY)) - return; - - foreach_context = (foreach_context_extra_data_t *)user_data; - if (foreach_context->foreach_break == true) - return; - - if (app_control_validate_internal_key(key)) - return; - - extra_data_cb = foreach_context->callback; - - if (extra_data_cb != NULL) { - bool stop_foreach = false; - - stop_foreach = !extra_data_cb(foreach_context->app_control, key, foreach_context->user_data); - - foreach_context->foreach_break = stop_foreach; - } -} - -EXPORT_API int app_control_foreach_extra_data(app_control_h app_control, app_control_extra_data_cb callback, void *user_data) -{ - foreach_context_extra_data_t foreach_context = { - .app_control = app_control, - .callback = callback, - .user_data = user_data, - .foreach_break = false - }; - - if (app_control_validate(app_control) || callback == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - bundle_foreach(app_control->data, app_control_cb_broker_bundle_iterator, &foreach_context); - - return APP_CONTROL_ERROR_NONE; -} - -typedef struct { - app_control_h app_control; - app_control_app_matched_cb callback; - void *user_data; - bool foreach_break; -} foreach_context_launchable_app_t; - -/* LCOV_EXCL_START */ -int app_control_cb_broker_foreach_app_matched(const char *package, void *data) -{ - foreach_context_launchable_app_t *foreach_context; - app_control_app_matched_cb app_matched_cb; - - if (package == NULL || data == NULL) { - app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - return -1; - } - - foreach_context = (foreach_context_launchable_app_t *)data; - if (foreach_context->foreach_break == true) - return -1; - - app_matched_cb = foreach_context->callback; - if (app_matched_cb != NULL) { - bool stop_foreach = false; - - stop_foreach = !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data); - - foreach_context->foreach_break = stop_foreach; - } - - return 0; -} -/* LCOV_EXCL_STOP */ - -EXPORT_API int app_control_foreach_app_matched(app_control_h app_control, app_control_app_matched_cb callback, void *user_data) -{ - foreach_context_launchable_app_t foreach_context = { - .app_control = app_control, - .callback = callback, - .user_data = user_data, - .foreach_break = false - }; - - if (app_control_validate(app_control) || callback == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - aul_svc_get_list_for_uid(app_control->data, app_control_cb_broker_foreach_app_matched, &foreach_context, getuid()); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_caller(app_control_h app_control, char **package) -{ - const char *bundle_value; - char *package_dup; - - if (app_control_validate(app_control) || package == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control->type != APP_CONTROL_TYPE_EVENT) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control handle type"); - - bundle_value = bundle_get_val(app_control->data, AUL_K_CALLER_APPID); - if (bundle_value == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to retrieve the appid of the caller"); - - package_dup = strdup(bundle_value); - if (package_dup == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); - - *package = package_dup; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_is_reply_requested(app_control_h app_control, bool *requested) -{ - const char *bundle_value; - - if (app_control_validate(app_control) || requested == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - if (app_control->type != APP_CONTROL_TYPE_EVENT) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid app_control handle type"); - - bundle_value = bundle_get_val(app_control->data, AUL_K_WAIT_RESULT); - if (bundle_value != NULL) - *requested = true; - else - *requested = false; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_import_from_bundle(app_control_h app_control, bundle *data) -{ - bundle *data_dup = NULL; - - if (app_control_validate(app_control) || data == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - data_dup = bundle_dup(data); - if (data_dup == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle"); - - if (app_control->data != NULL) - bundle_free(app_control->data); - - app_control->data = data_dup; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_export_as_bundle(app_control_h app_control, bundle **data) -{ - bundle *data_dup = NULL; - - if (app_control_validate(app_control) || data == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - data_dup = bundle_dup(app_control->data); - if (data_dup == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle"); - - *data = data_dup; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_request_transient_app(app_control_h app_control, unsigned int callee_id, app_control_host_res_fn cbfunc, void *data) -{ - int ret; - - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = aul_svc_request_transient_app(app_control->data, callee_id, (aul_svc_host_res_fn)cbfunc, data); - if (ret < 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_enable_app_started_result_event(app_control_h app_control) -{ - int ret; - - if (app_control_validate(app_control)) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = aul_svc_subscribe_launch_result(app_control->data, AUL_SVC_K_LAUNCH_RESULT_APP_STARTED); - if (ret < 0) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_instance_id(app_control_h app_control, const char *instance_id) -{ - int ret; - - if (app_control_validate(app_control) || instance_id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - ret = aul_svc_set_instance_id(app_control->data, instance_id); - if (ret < 0) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "Out of memory"); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_instance_id(app_control_h app_control, char **instance_id) -{ - const char *id; - - if (app_control_validate(app_control) || instance_id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - - id = aul_svc_get_instance_id(app_control->data); - if (id == NULL) - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, __FUNCTION__, "Failed to get the instance id"); - - *instance_id = strdup(id); - if (*instance_id == NULL) - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, __FUNCTION__, "Failed to duplicate the instance id"); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_send_launch_request_async(app_control_h app_control, - app_control_result_cb result_cb, - app_control_reply_cb reply_cb, - void *user_data) -{ - int ret; - - if (!app_control || !result_cb) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - ret = __send_launch_request(app_control, result_cb, - reply_cb, user_data); - - return ret; -} - -static int __launch_request_send_sync(struct launch_request_s *req) -{ - app_control_h request = req->app_control; - bundle *reply_bundle = NULL; - aul_svc_result_val appsvc_result; - int ret; - - if (req->implicit_default_operation) { - aul_svc_set_operation(request->data, - APP_CONTROL_OPERATION_DEFAULT); - } - - ret = aul_svc_send_launch_request_sync_for_uid(request->data, - req->id, &reply_bundle, &appsvc_result, getuid()); - - if (req->implicit_default_operation) - bundle_del(request->data, BUNDLE_KEY_OPERATION); - - if (ret < 0) { - return app_control_error(__launch_request_convert_error(ret), - __FUNCTION__, NULL); - } - - request->launch_pid = ret; - - ret = app_control_create_reply(reply_bundle, &req->reply); - bundle_free(reply_bundle); - if (ret != 0) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Failed to create reply handle"); - } - - req->result = __get_app_control_result(appsvc_result); - - return APP_CONTROL_ERROR_NONE; -} - -static int __send_launch_request_sync(app_control_h request, - app_control_h *reply, app_control_result_e *result) -{ - static launch_request_handler handlers[] = { - __launch_request_verify_operation, - __launch_request_send_sync, - }; - struct launch_request_s req = { - .implicit_default_operation = false, - .request_context = NULL, - .app_control = request, - .result_cb = NULL, - .reply_cb = NULL, - .user_data = NULL, - .reply = NULL, - .result = APP_CONTROL_RESULT_FAILED, - }; - int ret; - int i; - - if (app_control_validate(request)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - } - - req.id = __generate_request_id(); - for (i = 0; i < ARRAY_SIZE(handlers); i++) { - if (handlers[i]) { - ret = handlers[i](&req); - if (ret != APP_CONTROL_ERROR_NONE) - break; - } - } - - if (ret == APP_CONTROL_ERROR_NONE) { - if (reply) { - *reply = req.reply; - } else { - app_control_destroy(req.reply); - } - - if (result) - *result = req.result; - } - - return ret; -} - -EXPORT_API int app_control_send_launch_request_sync(app_control_h app_control, - app_control_h *reply, app_control_result_e *result) -{ - if (!app_control || !reply || !result) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - return __send_launch_request_sync(app_control, reply, result); -} - -static void __appcore_base_control_cb(bundle *b, void *user_data) -{ - struct app_control_action_s *h; - app_control_h app_control; - int r; - - h = (struct app_control_action_s *)user_data; - r = app_control_create_event(b, &app_control); - if (r != APP_CONTROL_ERROR_NONE) { - LOGE("Failed to create app-control handle"); - return; - } - - h->callback(h->action, app_control, h->user_data); - app_control_destroy(app_control); -} - -EXPORT_API int app_control_add_action_handler(const char *action, - app_control_action_cb callback, void *user_data, - app_control_action_h *handle) -{ - struct app_control_action_s *h; - int r; - - if (!action || !callback || !handle) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - h = calloc(1, sizeof(struct app_control_action_s)); - if (!h) { - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, "Out of memory"); - } - - h->action = strdup(action); - if (!h->action) { - free(h); - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, - "Failed to duplicate app-control action"); - } - - r = appcore_base_control_add(h->action, __appcore_base_control_cb, h, - &h->handle); - if (r != APPCORE_BASE_ERROR_NONE) { - free(h->action); - free(h); - switch (r) { - case APPCORE_BASE_ERROR_INVALID_PARAMETER: - return app_control_error( - APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, - "Invalid parameter"); - case APPCORE_BASE_ERROR_KEY_NOT_FOUND: - return app_control_error( - APP_CONTROL_ERROR_KEY_NOT_FOUND, - __FUNCTION__, - "AppControl ID is not found"); - case APPCORE_BASE_ERROR_IO_ERROR: - return app_control_error( - APP_CONTROL_ERROR_IO_ERROR, - __FUNCTION__, - "IO error"); - default: - return app_control_error( - APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, - "Out of memory"); - } - } - - h->callback = callback; - h->user_data = user_data; - - *handle = h; - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_remove_action_handler(app_control_action_h handle) -{ - if (!handle) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - if (handle->handle) - appcore_base_control_remove(handle->handle); - - if (handle->action) - free(handle->action); - - free(handle); - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_caller_instance_id(app_control_h app_control, - const char *instance_id) -{ - int r; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - if (instance_id != NULL) { - r = aul_svc_set_caller_instance_id(app_control->data, - instance_id); - if (r != AUL_SVC_RET_OK) { - return app_control_error( - APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, "Out of memory"); - } - } else { - aul_svc_set_caller_instance_id(app_control->data, instance_id); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_set_component_id(app_control_h app_control, - const char *component_id) -{ - int r; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - r = aul_svc_set_comp_id(app_control->data, component_id); - if (r != AUL_SVC_RET_OK && component_id != NULL) { - return app_control_error(APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, "Out of memory"); - } - - return APP_CONTROL_ERROR_NONE; -} - -EXPORT_API int app_control_get_component_id(app_control_h app_control, - char **component_id) -{ - const char *comp_id; - - if (app_control_validate(app_control) || !component_id) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - comp_id = aul_svc_get_comp_id(app_control->data); - if (comp_id) { - *component_id = strdup(comp_id); - if (*component_id == NULL) { - return app_control_error( - APP_CONTROL_ERROR_OUT_OF_MEMORY, - __FUNCTION__, "Out of memory"); - } - } else { - *component_id = NULL; - } - - return APP_CONTROL_ERROR_NONE; -} - -static int __resume_request_verify_appid(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - const char *appid; - - appid = aul_svc_get_appid(app_control->data); - if (!appid) { - return app_control_error(APP_CONTROL_ERROR_APP_NOT_FOUND, - __FUNCTION__, - "Application ID must be specified"); - } - - return APP_CONTROL_ERROR_NONE; -} - -static int __resume_request_send(struct launch_request_s *req) -{ - app_control_h app_control = req->app_control; - aul_svc_err_cb result_cb = app_control_request_result_broker; - int ret; - - __add_pending_item(req->id); - - ret = aul_svc_send_resume_request_for_uid(app_control->data, - req->id, result_cb, req->request_context, getuid()); - - if (ret < 0) { - __remove_pending_item(req->id); - return app_control_error(__launch_request_convert_error(ret), - __FUNCTION__, NULL); - } - - return APP_CONTROL_ERROR_NONE; -} - -static int __send_resume_request(app_control_h app_control, - app_control_result_cb result_cb, - void *user_data) -{ - static launch_request_handler handlers[] = { - __resume_request_verify_appid, - __launch_request_prepare_request_context, - __resume_request_send, - __launch_request_complete, - }; - struct launch_request_s req = { - .implicit_default_operation = false, - .request_context = NULL, - .app_control = app_control, - .result_cb = result_cb, - .reply_cb = NULL, - .user_data = user_data, - .reply = NULL, - .result = APP_CONTROL_RESULT_FAILED, - }; - int ret; - int i; - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, NULL); - } - - req.id = __generate_request_id(); - for (i =0; i < ARRAY_SIZE(handlers); i++) { - if (handlers[i]) { - ret = handlers[i](&req); - if (ret != APP_CONTROL_ERROR_NONE) - break; - } - } - - if (ret != APP_CONTROL_ERROR_NONE && req.request_context) { - if (req.request_context->app_control) - app_control_destroy(req.request_context->app_control); - - free(req.request_context); - } - - return ret; -} - -EXPORT_API int app_control_send_resume_request(app_control_h app_control, - app_control_result_cb result_cb, - void *user_data) -{ - if (!app_control || !result_cb) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - return __send_resume_request(app_control, result_cb, user_data); -} - -static int __convert_aul_error(int result) -{ - switch (result) { - case AUL_R_EINVAL: - return APP_CONTROL_ERROR_INVALID_PARAMETER; - case AUL_R_ENOMEM: - return APP_CONTROL_ERROR_OUT_OF_MEMORY; - case AUL_R_EILLACC: - return APP_CONTROL_ERROR_PERMISSION_DENIED; - default: - return APP_CONTROL_ERROR_IO_ERROR; - } -} - -EXPORT_API int app_control_prepare_app_defined_loader(app_control_h app_control, - const char *loader_id) -{ - const char *loader_name = loader_id; /* for readability */ - int ret; - - if (!app_control || !loader_name) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Inivalid parameter"); - } - - if (app_control_validate(app_control)) { - return app_control_error(APP_CONTROL_ERROR_INVALID_PARAMETER, - __FUNCTION__, "Invalid parameter"); - } - - ret = aul_prepare_app_defined_loader(loader_name); - if (ret < 0) { - return app_control_error(__convert_aul_error(ret), - __FUNCTION__, - "Failed to prepare app defined loader"); - } - - bundle_del(app_control->data, AUL_K_APP_DEFINED_LOADER); - bundle_add(app_control->data, AUL_K_APP_DEFINED_LOADER, loader_name); - - ret = aul_svc_set_loader_id(app_control->data, ret); - if (ret < 0) { - if (ret == AUL_SVC_RET_EINVAL) - ret = APP_CONTROL_ERROR_INVALID_PARAMETER; - else - ret = APP_CONTROL_ERROR_OUT_OF_MEMORY; - - return app_control_error(ret, __FUNCTION__, - "Failed to set loader id"); - } - - return APP_CONTROL_ERROR_NONE; -} diff --git a/src/app-control/app_control.cc b/src/app-control/app_control.cc new file mode 100644 index 0000000..59c497d --- /dev/null +++ b/src/app-control/app_control.cc @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2021 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. + */ + +#include +#include +#include +#include +#include + +#include "app-control/app_control.hh" +#include "app-control/app_control_broker.hh" +#include "app-control/exception.hh" +#include "app-control/log_private.hh" +#include "app-control/util.hh" + +namespace app_control { +namespace { + +const char kBundlePrefixAul[] = "__AUL_"; +const char kBundlePrefixService[] = "__APP_SVC_"; +const char kBundlePkgName[] = "__APP_SVC_PKG_NAME__"; + +} // namespace + +AppControl::AppControl(Type type) : type_(type) { +} + +AppControl::AppControl(tizen_base::Bundle data, Type type) + : data_(std::move(data)), type_(type) { +} + +AppControl::~AppControl() { + if (data_.GetType(AUL_SVC_K_LAUNCH_RESULT_APP_STARTED) != BUNDLE_TYPE_NONE) { + if (type_ == Type::Request && launched_pid_ > 0) + aul_remove_caller_cb(launched_pid_, this); + } +} + +AppControl::AppControl(const AppControl& app_control) { + data_ = app_control.data_; + type_ = app_control.type_; + launched_pid_ = app_control.launched_pid_; +} + +AppControl& AppControl::operator = (const AppControl& app_control) { + if (this != &app_control) { + data_ = app_control.data_; + type_ = app_control.type_; + launched_pid_ = app_control.launched_pid_; + } + + return *this; +} + +AppControl::AppControl(AppControl&& app_control) noexcept { + data_ = std::move(app_control.data_); + + type_ = app_control.type_; + app_control.type_ = Type::None; + + launched_pid_ = app_control.launched_pid_; + app_control.launched_pid_ = -1; +} + +AppControl& AppControl::operator = (AppControl&& app_control) noexcept { + if (this != &app_control) { + data_ = std::move(app_control.data_); + + type_ = app_control.type_; + app_control.type_ = Type::None; + + launched_pid_ = app_control.launched_pid_; + app_control.launched_pid_ = -1; + } + + return *this; +} + +void AppControl::SetOperation(const std::string& operation) { + int ret = aul_svc_set_operation(data_.GetHandle(), operation.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetUri(const std::string& uri) { + int ret = aul_svc_set_uri(data_.GetHandle(), uri.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetMime(const std::string& mime) { + int ret = aul_svc_set_mime(data_.GetHandle(), mime.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetCategory(const std::string& category) { + int ret = aul_svc_set_category(data_.GetHandle(), category.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetAppId(const std::string& app_id) { + int ret = aul_svc_set_appid(data_.GetHandle(), app_id.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetComponentId(const std::string& component_id) { + int ret = aul_svc_set_comp_id(data_.GetHandle(), component_id.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetLaunchMode(LaunchMode launch_mode) { + if (launch_mode != LaunchMode::Single && launch_mode != LaunchMode::Group) + THROW(Error::InvalidParameter); + + int ret = aul_svc_set_launch_mode(data_.GetHandle(), + launch_mode == LaunchMode::Group ? "group" : "single"); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetInstanceId(const std::string& instance_id) { + int ret = aul_svc_set_instance_id(data_.GetHandle(), instance_id.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetCallerInstanceId(const std::string& instance_id) { + int ret = aul_svc_set_caller_instance_id(data_.GetHandle(), + instance_id.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetLoaderId(int loader_id) { + int ret = aul_svc_set_loader_id(data_.GetHandle(), loader_id); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::SetAppDefinedLoader(const std::string& loader_name) { + data_.Delete(AUL_K_APP_DEFINED_LOADER); + data_.Add(AUL_K_APP_DEFINED_LOADER, loader_name); +} + +std::string AppControl::GetOperation() const { + const char* operation = aul_svc_get_operation(data_.GetHandle()); + if (operation == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(operation); +} + +std::string AppControl::GetUri() const { + const char* uri = aul_svc_get_uri(data_.GetHandle()); + if (uri == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(uri); +} + +std::string AppControl::GetMime() const { + const char* mime = aul_svc_get_mime(data_.GetHandle()); + if (mime == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(mime); +} + +std::string AppControl::GetCategory() const { + const char* category = aul_svc_get_category(data_.GetHandle()); + if (category == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(category); +} + +std::string AppControl::GetAppId() const { + const char* app_id = aul_svc_get_appid(data_.GetHandle()); + if (app_id == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(app_id); +} + +std::string AppControl::GetCaller() const { + if (type_ != Type::Event) + THROW(static_cast(Error::InvalidParameter)); + + std::string caller = data_.GetString(AUL_K_CALLER_APPID); + if (caller.empty()) + THROW(static_cast(Error::KeyNotFound)); + + return caller; +} + +std::string AppControl::GetComponentId() const { + const char* component_id = aul_svc_get_comp_id(data_.GetHandle()); + if (component_id == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(component_id); +} + +std::string AppControl::GetInstanceId() const { + const char* instance_id = aul_svc_get_instance_id(data_.GetHandle()); + if (instance_id == nullptr) + THROW(static_cast(Error::KeyNotFound)); + + return std::string(instance_id); +} + +LaunchMode AppControl::GetLaunchMode() const { + const char* launch_mode = aul_svc_get_launch_mode(data_.GetHandle()); + if (launch_mode == nullptr) + return LaunchMode::Single; + + if (!strcmp(launch_mode, "group")) + return LaunchMode::Group; + else if (!strcmp(launch_mode, "single")) + return LaunchMode::Single; + else + THROW(static_cast(Error::InvalidParameter)); +} + +void AppControl::RemoveOperation() { + aul_svc_set_operation(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveUri() { + aul_svc_set_uri(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveMime() { + aul_svc_set_mime(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveCategory() { + aul_svc_set_category(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveAppId() { + data_.Delete(kBundlePkgName); +} + +void AppControl::RemoveComponentId() { + aul_svc_set_comp_id(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveInstanceId() { + aul_svc_set_instance_id(data_.GetHandle(), nullptr); +} + +void AppControl::RemoveCallerInstanceId() { + aul_svc_set_caller_instance_id(data_.GetHandle(), nullptr); +} + +void AppControl::AddExtraData(const std::string& key, + const std::string& value) { + if (key.empty() || value.empty()) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + int ret = aul_svc_add_data(data_.GetHandle(), key.c_str(), value.c_str()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::AddExtraDataArray(const std::string& key, + const std::vector& value) { + if (key.empty() || value.size() == 0) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + std::vector value_array; + int value_size = value.size(); + for (auto i = 0; i < value_size; ++i) + value_array.push_back(value[i].c_str()); + + int ret = aul_svc_add_data_array(data_.GetHandle(), key.c_str(), + value_array.data(), value_array.size()); + if (ret != AUL_SVC_RET_OK) + THROW(Util::AulSvcErrorConvert(ret)); +} + +void AppControl::RemoveExtraData(const std::string& key) { + if (key.empty()) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + if (data_.Delete(key) != BUNDLE_ERROR_NONE) + THROW(static_cast(Error::KeyNotFound)); +} + +std::string AppControl::GetExtraData(const std::string& key) const { + if (key.empty()) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + const char* value = aul_svc_get_data(data_.GetHandle(), key.c_str()); + if (value == nullptr) { + if (get_last_result() == BUNDLE_ERROR_KEY_NOT_AVAILABLE) + THROW(static_cast(Error::KeyNotFound)); + else + THROW(static_cast(Error::InvalidDataType)); + } + + return std::string(value); +} + +std::vector AppControl::GetExtraDataArray( + const std::string& key) const { + if (key.empty()) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + int len = 0; + const char** value_array = aul_svc_get_data_array(data_.GetHandle(), + key.c_str(), &len); + if (value_array == nullptr) { + if (get_last_result() == BUNDLE_ERROR_KEY_NOT_AVAILABLE) + THROW(static_cast(Error::KeyNotFound)); + else + THROW(static_cast(Error::InvalidDataType)); + } + + std::vector v; + for (int i = 0; i < len; ++i) + v.emplace_back(value_array[i]); + + return v; +} + +bool AppControl::IsExtraDataArray(const std::string& key) const { + if (key.empty()) + THROW(static_cast(Error::InvalidParameter)); + + if (!ValidateInternalKey(key)) + THROW(static_cast(Error::KeyRejected)); + + if (aul_svc_data_is_array(data_.GetHandle(), key.c_str())) + return true; + + return false; +} + +std::vector AppControl::GetExtraDataKeys() { + std::vector keys; + for (auto& key_info : data_.GetKeys()) { + if (!ValidateInternalKey(key_info.GetName())) + continue; + + keys.emplace_back(key_info.GetName()); + } + + return keys; +} + +std::vector AppControl::GetMatchedAppIds() { + char** appid_array = nullptr; + unsigned int len = 0; + int ret = aul_svc_get_appid_array(data_.GetHandle(), getuid(), + &appid_array, &len); + if (ret != AUL_SVC_RET_OK) + return {}; + + std::vector app_ids; + for (unsigned int i = 0; i < len; ++i) + app_ids.push_back(appid_array[i]); + + aul_svc_free_appid_array(appid_array, len); + return app_ids; +} + +bool AppControl::IsReplyRequested() const { + if (type_ != Type::Event) + THROW(static_cast(Error::InvalidParameter)); + + if (data_.GetType(AUL_K_WAIT_RESULT) != BUNDLE_TYPE_NONE) + return true; + + return false; +} + +void AppControl::EnableAppStartedResultEvent() { + int ret = aul_svc_subscribe_launch_result(data_.GetHandle(), + AUL_SVC_K_LAUNCH_RESULT_APP_STARTED); + if (ret != AUL_SVC_RET_OK) + THROW(static_cast(Error::InvalidParameter)); +} + +bool AppControl::HasAppStartedResultEvent() const { + bundle_type type = data_.GetType(AUL_SVC_K_LAUNCH_RESULT_APP_STARTED); + if (type != BUNDLE_TYPE_NONE) + return true; + + return false; +} + +void AppControl::SetLaunchedPid(int launched_pid) { + launched_pid_ = launched_pid; +} + +int AppControl::GetLaunchedPid() const { + return launched_pid_; +} + +AppControl::Type AppControl::GetType() const { + return type_; +} + +void AppControl::SetBundle(tizen_base::Bundle data) { + data_ = std::move(data); +} + +bundle* AppControl::ToBundle() const { + return data_.GetHandle(); +} + +bool AppControl::ValidateInternalKey(const std::string& key) { + if (key.compare(0, strlen(kBundlePrefixAul), + kBundlePrefixAul) == 0) + return false; + + if (key.compare(0, strlen(kBundlePrefixService), + kBundlePrefixService) == 0) + return false; + + return true; +} + +} // namespace app_control diff --git a/src/app-control/app_control.hh b/src/app-control/app_control.hh new file mode 100644 index 0000000..1d33b69 --- /dev/null +++ b/src/app-control/app_control.hh @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_APP_CONTROL_HH_ +#define APP_CONTROL_APP_CONTROL_HH_ + +#include + +#include +#include +#include +#include + +#include "app-control/error.hh" +#include "app-control/launch_mode.hh" +#include "app-control/result.hh" + +namespace app_control { + +class AppControl { + public: + enum Type { + None, + Request, + Event, + Reply, + }; + + AppControl(Type type = Type::Request); + AppControl(tizen_base::Bundle data, Type type = Type::Request); + virtual ~AppControl(); + + AppControl(const AppControl& app_control); + AppControl& operator = (const AppControl& app_control); + + AppControl(AppControl&& app_control) noexcept; + AppControl& operator = (AppControl&& app_control) noexcept; + + void SetOperation(const std::string& operation); + void SetUri(const std::string& uri); + void SetMime(const std::string& mime); + void SetCategory(const std::string& category); + void SetAppId(const std::string& app_id); + void SetComponentId(const std::string& component_id); + void SetLaunchMode(LaunchMode launch_mode); + void SetInstanceId(const std::string& instance_id); + void SetCallerInstanceId(const std::string& instance_id); + void SetLoaderId(int loader_id); + void SetAppDefinedLoader(const std::string& loader_name); + + std::string GetOperation() const; + std::string GetUri() const; + std::string GetMime() const; + std::string GetCategory() const; + std::string GetAppId() const; + std::string GetCaller() const; + std::string GetComponentId() const; + std::string GetInstanceId() const; + LaunchMode GetLaunchMode() const; + + void RemoveOperation(); + void RemoveUri(); + void RemoveMime(); + void RemoveCategory(); + void RemoveAppId(); + void RemoveComponentId(); + void RemoveInstanceId(); + void RemoveCallerInstanceId(); + + void AddExtraData(const std::string& key, const std::string& value); + void AddExtraDataArray(const std::string& key, + const std::vector& value); + void RemoveExtraData(const std::string& key); + std::string GetExtraData(const std::string& key) const; + std::vector GetExtraDataArray(const std::string& key) const; + bool IsExtraDataArray(const std::string& key) const; + std::vector GetExtraDataKeys(); + std::vector GetMatchedAppIds(); + + bool IsReplyRequested() const; + void EnableAppStartedResultEvent(); + bool HasAppStartedResultEvent() const; + + void SetLaunchedPid(int pid); + int GetLaunchedPid() const; + + Type GetType() const; + + void SetBundle(tizen_base::Bundle data); + bundle* ToBundle() const; + + private: + static bool ValidateInternalKey(const std::string& key); + + private: + tizen_base::Bundle data_; + Type type_; + int launched_pid_ = -1; +}; + +} // namespace app_control + +#endif // APP_CONTROL_APP_CONTROL_HH_ diff --git a/src/app-control/app_control_action.cc b/src/app-control/app_control_action.cc new file mode 100644 index 0000000..9529047 --- /dev/null +++ b/src/app-control/app_control_action.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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. + */ + +#include "app-control/app_control_action.hh" +#include "app-control/error.hh" +#include "app-control/exception.hh" +#include "app-control/log_private.hh" + +namespace app_control { + +AppControlAction::AppControlAction(std::string action, IEvent* listener) + : action_(std::move(action)), listener_(listener) { + int ret = appcore_base_control_add(action_.c_str(), + AppcoreBaseControlCb, this, &handle_); + if (ret != APPCORE_BASE_ERROR_NONE) + THROW(AppcoreBaseErrorConvert(ret)); +} + +AppControlAction::~AppControlAction() { + if (handle_ != nullptr) + appcore_base_control_remove(handle_); +} + +const std::string& AppControlAction::GetAction() const { + return action_; +} + +void AppControlAction::AppcoreBaseControlCb(bundle* b, void* user_data) { + auto* handle = static_cast(user_data); + auto* listener = handle->listener_; + listener->OnAction(handle->action_, b); +} + +int AppControlAction::AppcoreBaseErrorConvert(int ret) { + switch (ret) { + case APPCORE_BASE_ERROR_INVALID_PARAMETER: + return static_cast(Error::InvalidParameter); + case APPCORE_BASE_ERROR_KEY_NOT_FOUND: + return static_cast(Error::KeyNotFound); + case APPCORE_BASE_ERROR_IO_ERROR: + return static_cast(Error::IOError); + default: + return static_cast(Error::OutOfMemory); + } +} + +} // namespace app_control diff --git a/src/app-control/app_control_action.hh b/src/app-control/app_control_action.hh new file mode 100644 index 0000000..e9546e0 --- /dev/null +++ b/src/app-control/app_control_action.hh @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_APP_CONTROL_ACTION_HH_ +#define APP_CONTROL_APP_CONTROL_ACTION_HH_ + +#include + +#include + +namespace app_control { + +class AppControlAction { + public: + class IEvent { + public: + virtual void OnAction(const std::string& action, bundle* data) = 0; + }; + + AppControlAction(std::string action, IEvent* listener); + virtual ~AppControlAction(); + + const std::string& GetAction() const; + + private: + static void AppcoreBaseControlCb(bundle* b, void* user_data); + static int AppcoreBaseErrorConvert(int ret); + + private: + std::string action_; + IEvent* listener_; + appcore_base_control_h handle_ = nullptr; +}; + +} // namespace app_control + +#endif // APP_CONTROL_APP_CONTROL_ACTION_HH_ diff --git a/src/app-control/app_control_broker.cc b/src/app-control/app_control_broker.cc new file mode 100644 index 0000000..5162d4c --- /dev/null +++ b/src/app-control/app_control_broker.cc @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2021 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. + */ + +#include +#include +#include +#include + +#include "app-control/app_control_broker.hh" +#include "app-control/exception.hh" +#include "app-control/util.hh" + +namespace app_control { + +std::atomic AppControlBroker::inst_; +std::mutex AppControlBroker::mutex_; + +AppControlBroker* AppControlBroker::GetInst() { + AppControlBroker* inst = inst_.load(std::memory_order_acquire); + if (inst == nullptr) { + std::lock_guard lock(mutex_); + inst = inst_.load(std::memory_order_relaxed); + if (inst == nullptr) { + inst = new AppControlBroker(); + inst_.store(inst, std::memory_order_release); + } + } + + return inst; +} + +void AppControlBroker::AddRequestContext( + std::shared_ptr request_context) { + std::lock_guard lock(GetRecMutex()); + contexts_[request_context->GetRequestId()] = request_context; +} + +void AppControlBroker::RemoveRequestContext(int id) { + std::lock_guard lock(GetRecMutex()); + auto found = contexts_.find(id); + if (found == contexts_.end()) + return; + + contexts_.erase(found); +} + +std::shared_ptr AppControlBroker::FindRequestContext(int id) { + std::lock_guard lock(GetRecMutex()); + auto found = contexts_.find(id); + if (found == contexts_.end()) + return nullptr; + + return found->second; +} + +void AppControlBroker::PushPendingItem(std::shared_ptr item) { + std::lock_guard lock(GetRecMutex()); + items_[item->GetId()] = item; +} + +std::shared_ptr AppControlBroker::PopPendingItem(int id) { + std::lock_guard lock(GetRecMutex()); + auto found = items_.find(id); + if (found == items_.end()) + return nullptr; + + auto item = found->second; + items_.erase(found); + return item; +} + +std::shared_ptr AppControlBroker::FindPendingItem(int id) { + std::lock_guard lock(GetRecMutex()); + auto found = items_.find(id); + if (found == items_.end()) + return nullptr; + + return found->second; +} + +std::recursive_mutex& AppControlBroker::GetRecMutex() const { + return rec_mutex_; +} + +void AppControlBroker::FlushPendingItem(int id) { + auto item = FindPendingItem(id); + if (item == nullptr) + return; + + g_idle_add([](gpointer data) -> gboolean { + int req_id = GPOINTER_TO_INT(data); + auto* broker = AppControlBroker::GetInst(); + auto item = broker->FindPendingItem(req_id); + if (item == nullptr) + return G_SOURCE_REMOVE; + + auto result_info = item->GetResultInfo(); + if (result_info != nullptr) { + AppControlResultBroker(req_id, result_info->GetResult(), + result_info->GetData()); + item->SetResultInfo(nullptr); + return G_SOURCE_CONTINUE; + } + + auto reply_info = item->GetReplyInfo(); + if (reply_info != nullptr) { + AppControlReplyBroker(reply_info->GetBundle().GetHandle(), req_id, + static_cast(reply_info->GetResult()), + reply_info->GetData()); + item->SetReplyInfo(nullptr); + } + + broker->PopPendingItem(req_id); + return G_SOURCE_REMOVE; + }, GINT_TO_POINTER(id)); +} + +void AppControlBroker::AppControlResultBroker(int req_id, int result, + void* user_data) { + auto* broker = AppControlBroker::GetInst(); + auto request_context = broker->FindRequestContext(req_id); + if (request_context == nullptr) { + _E("Invalid request"); + return; + } + + auto app_control = request_context->GetAppControl(); + app_control->SetLaunchedPid(result); + auto result_cb = request_context->GetResultCb(); + if (result_cb != nullptr) { + int error = APP_CONTROL_ERROR_NONE; + if (result < 0) + error = Util::AulSvcErrorConvert(result); + + result_cb(app_control.get(), static_cast(error), + request_context->GetUserData()); + } + + if (result < 0 || request_context->GetReplyCb() == nullptr) { + broker->RemoveRequestContext(req_id); + return; + } + + HandleAppStartedResult(app_control.get(), req_id); +} + +void AppControlBroker::AppControlResultCb(int req_id, int result, + void* user_data) { + auto* broker = AppControlBroker::GetInst(); + auto item = broker->FindPendingItem(req_id); + if (item != nullptr) { + item->SetResultInfo(std::make_shared(result, user_data)); + _W("Result info is pending"); + return; + } + + AppControlResultBroker(req_id, result, user_data); +} + +void AppControlBroker::AppControlReplyBroker(bundle* b, int req_id, + aul_svc_result_val result, void* user_data) { + auto* broker = AppControlBroker::GetInst(); + auto request_context = broker->FindRequestContext(req_id); + if (request_context == nullptr) + return; + + auto reply_cb = request_context->GetReplyCb(); + if (reply_cb == nullptr) { + _E("Invalid callback"); + return; + } + + auto request = request_context->GetAppControl(); + app_control_result_e res = Util::AulSvcResultConvert(result); + AppControl reply(tizen_base::Bundle(b), AppControl::Type::Reply); + reply_cb(request.get(), &reply, res, request_context->GetUserData()); + broker->RemoveRequestContext(req_id); +} + +void AppControlBroker::AppControlReplyCb(bundle* b, int req_id, + aul_svc_result_val result, void* user_data) { + auto* broker = AppControlBroker::GetInst(); + auto item = broker->FindPendingItem(req_id); + if (item != nullptr) { + item->SetReplyInfo(std::make_shared( + tizen_base::Bundle(b, true, true), + static_cast(result), user_data)); + _W("Reply info is pending"); + return; + } + + AppControlReplyBroker(b, req_id, result, user_data); +} + +void AppControlBroker::HandleAppStartedResult(AppControl* app_control, + int req_id) { + int launched_pid = app_control->GetLaunchedPid(); + if (!app_control->HasAppStartedResultEvent()) { + aul_add_caller_cb(launched_pid, + [](int launched_pid, void* data) { + AppControl* control = static_cast(data); + if (control == nullptr) + return; + + control->SetLaunchedPid(launched_pid); + }, static_cast(app_control)); + return; + } + + char callee[256] = { 0, }; + int ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee)); + if (ret != AUL_R_OK) + _E("Failed to get application ID. pid(%d)", launched_pid); + + auto* broker = AppControlBroker::GetInst(); + auto request_context = broker->FindRequestContext(req_id); + if (request_context != nullptr) + request_context->GetAppControl()->SetLaunchedPid(launched_pid); + + aul_add_caller_cb(launched_pid, + [](int launched_pid, void* data) { + int req_id = GPOINTER_TO_INT(data); + auto* broker = AppControlBroker::GetInst(); + auto request_context = broker->FindRequestContext(req_id); + if (request_context == nullptr) + return; + + _I("AppControl async result callback. callee_pid(%d)", launched_pid); + auto reply_cb = request_context->GetReplyCb(); + if (reply_cb == nullptr) { + _E("Invalid callback"); + return; + } + + auto app_control = request_context->GetAppControl(); + AppControl reply(tizen_base::Bundle(app_control->ToBundle()), + AppControl::Type::Event); + + char callee[256] = { 0, }; + int ret = aul_app_get_appid_bypid(launched_pid, callee, sizeof(callee)); + if (ret != AUL_R_OK) + _E("Failed to get application ID. pid(%d)", launched_pid); + else + reply.SetAppId(callee); + + reply_cb(app_control.get(), &reply, APP_CONTROL_RESULT_APP_STARTED, + request_context->GetUserData()); + }, GINT_TO_POINTER(req_id)); + + if (strcmp(callee, APP_SELECTOR) && strcmp(callee, SHARE_PANEL)) + aul_invoke_caller_cb(GINT_TO_POINTER(req_id)); +} + +int AppControlBroker::CheckAppControl(AppControl* app_control) { + std::string operation; + try { + operation = app_control->GetOperation(); + } catch (Exception& e) { + operation = APP_CONTROL_OPERATION_DEFAULT; + } + + if (operation == APP_CONTROL_OPERATION_LAUNCH_ON_EVENT) { + _E("Not supported operation value"); + return APP_CONTROL_ERROR_LAUNCH_REJECTED; + } + + if (operation == APP_CONTROL_OPERATION_DEFAULT) { + try { + std::string app_id = app_control->GetAppId(); + } catch (Exception& e) { + _E("Application ID MUST be specified"); + return APP_CONTROL_ERROR_APP_NOT_FOUND; + } + } + + return APP_CONTROL_ERROR_NONE; +} + +void AppControlBroker::CopyCalleeInfo(AppControl* dst, AppControl* src) { + try { + auto app_id = src->GetAppId(); + dst->SetAppId(app_id); + } catch (Exception& e) { + SECURE_LOGD("Failed to get application ID"); + } + + try { + auto instance_id = src->GetInstanceId(); + dst->SetInstanceId(instance_id); + } catch (Exception& e) { + SECURE_LOGD("Failed to get instance ID"); + } +} + +void AppControlBroker::SendLaunchRequest(AppControl* app_control, + std::shared_ptr context) { + int ret = CheckAppControl(app_control); + if (ret != APP_CONTROL_ERROR_NONE) + THROW(ret); + + int req_id = context->GetRequestId(); + aul_svc_res_fn reply_cb = + context->GetReplyCb() ? AppControlReplyCb : nullptr; + aul_svc_err_cb result_cb = + context->GetResultCb() ? AppControlResultCb : nullptr; + + if (reply_cb != nullptr || result_cb != nullptr) { + AddRequestContext(context); + PushPendingItem(std::make_shared(req_id)); + } + + if (result_cb != nullptr) { + ret = aul_svc_send_launch_request_for_uid(app_control->ToBundle(), + req_id, reply_cb, result_cb, nullptr, getuid()); + } else { + ret = aul_svc_run_service_for_uid(app_control->ToBundle(), + req_id, reply_cb, nullptr, getuid()); + } + + if (ret < 0) { + _E("Failed to send launch request. error(%d)", ret); + PopPendingItem(req_id); + RemoveRequestContext(req_id); + THROW(Util::AulSvcErrorConvert(ret)); + } + + app_control->SetLaunchedPid(ret); + if (context->GetAppControl() != nullptr) + CopyCalleeInfo(context->GetAppControl().get(), app_control); + + if (result_cb != nullptr) { + FlushPendingItem(req_id); + return; + } + + if (reply_cb == nullptr) + return; + + HandleAppStartedResult(app_control, req_id); + FlushPendingItem(req_id); +} + +void AppControlBroker::SendLaunchRequest(AppControl* app_control, + AppControl** reply, app_control_result_e* result) { + int ret = CheckAppControl(app_control); + if (ret != APP_CONTROL_ERROR_NONE) + THROW(ret); + + bundle* b = nullptr; + aul_svc_result_val res; + int req_id = RequestContext::GenerateId(); + ret = aul_svc_send_launch_request_sync_for_uid(app_control->ToBundle(), + req_id, &b, &res, getuid()); + if (ret < 0) { + _E("Failed to send launch request. error(%d)", ret); + THROW(Util::AulSvcErrorConvert(ret)); + } + + app_control->SetLaunchedPid(ret); + *reply = new (std::nothrow) AppControl( + tizen_base::Bundle(b, false, true), AppControl::Type::Reply); + if (*reply == nullptr) { + _E("Failed to create reply handle"); + THROW(APP_CONTROL_ERROR_OUT_OF_MEMORY); + } + + *result = Util::AulSvcResultConvert(res); +} + +void AppControlBroker::SendResumeRequest(AppControl* app_control, + std::shared_ptr context) { + try { + std::string app_id = app_control->GetAppId(); + } catch (Exception& e) { + _E("Application ID MUST be specified"); + THROW(APP_CONTROL_ERROR_APP_NOT_FOUND); + } + + int req_id = context->GetRequestId(); + AddRequestContext(context); + PushPendingItem(std::make_shared(req_id)); + aul_svc_err_cb result_cb = AppControlResultCb; + + int ret = aul_svc_send_resume_request_for_uid(app_control->ToBundle(), + req_id, result_cb, nullptr, getuid()); + if (ret < 0) { + _E("Failed to send resume request. error(%d)", ret); + PopPendingItem(req_id); + RemoveRequestContext(req_id); + THROW(Util::AulSvcErrorConvert(ret)); + } + + CopyCalleeInfo(context->GetAppControl().get(), app_control); + FlushPendingItem(req_id); +} + +} // namespace app_control diff --git a/src/app-control/app_control_broker.hh b/src/app-control/app_control_broker.hh new file mode 100644 index 0000000..0416d41 --- /dev/null +++ b/src/app-control/app_control_broker.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_APP_CONTROL_BROKER_HH_ +#define APP_CONTROL_APP_CONTROL_BROKER_HH_ + +#include +#include +#include + +#include +#include +#include +#include + +#include "app-control/request_context.hh" +#include "app-control/pending_item.hh" +#include "include/app_control.h" + +namespace app_control { + +class AppControlBroker { + private: + AppControlBroker() = default; + ~AppControlBroker() = default; + + public: + static AppControlBroker* GetInst(); + + void SendLaunchRequest(AppControl* app_control, + std::shared_ptr request_context); + void SendLaunchRequest(AppControl* app_control, + AppControl** reply, app_control_result_e* result); + void SendResumeRequest(AppControl* app_control, + std::shared_ptr request_context); + + private: + void AddRequestContext(std::shared_ptr request_context); + void RemoveRequestContext(int id); + std::shared_ptr FindRequestContext(int id); + + void PushPendingItem(std::shared_ptr item); + std::shared_ptr PopPendingItem(int id); + std::shared_ptr FindPendingItem(int id); + void FlushPendingItem(int id); + + std::recursive_mutex& GetRecMutex() const; + + static void AppControlResultBroker(int req_id, int result, void* user_data); + static void AppControlResultCb(int req_id, int result, void* user_data); + static void AppControlReplyBroker(bundle* b, int req_id, + aul_svc_result_val result, void* user_data); + static void AppControlReplyCb(bundle* b, int req_id, + aul_svc_result_val result, void* user_data); + static void HandleAppStartedResult(AppControl* app_control, int req_id); + static int CheckAppControl(AppControl* app_control); + static void CopyCalleeInfo(AppControl* dst, AppControl* src); + + private: + static std::atomic inst_; + static std::mutex mutex_; + + private: + std::map> contexts_; + std::map> items_; + mutable std::recursive_mutex rec_mutex_; +}; + +} // namespace app_control + +#endif // APP_CONTROL_APP_CONTROL_BROKER_HH_ diff --git a/src/app-control/error.hh b/src/app-control/error.hh new file mode 100644 index 0000000..f0d9c3b --- /dev/null +++ b/src/app-control/error.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_ERROR_HH_ +#define APP_CONTROL_ERROR_HH_ + +#include + +namespace app_control { + +enum Error : int { + None = TIZEN_ERROR_NONE, + InvalidParameter = TIZEN_ERROR_INVALID_PARAMETER, + OutOfMemory = TIZEN_ERROR_OUT_OF_MEMORY, + AppNotFound = TIZEN_ERROR_APPLICATION | 0x21, + KeyNotFound = TIZEN_ERROR_KEY_NOT_AVAILABLE, + KeyRejected = TIZEN_ERROR_KEY_REJECTED, + InvalidDataType = TIZEN_ERROR_APPLICATION | 0x22, + LaunchRejected = TIZEN_ERROR_APPLICATION | 0x23, + PermissionDenied = TIZEN_ERROR_PERMISSION_DENIED, + LaunchFailed = TIZEN_ERROR_APPLICATION | 0x24, + TimedOut = TIZEN_ERROR_TIMED_OUT, + IOError = TIZEN_ERROR_IO_ERROR, +}; + +} // namespace app_control + +#endif // APP_CONTROL_ERROR_HH_ diff --git a/src/app-control/exception.hh b/src/app-control/exception.hh new file mode 100644 index 0000000..05ab5d3 --- /dev/null +++ b/src/app-control/exception.hh @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * 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 APP_CONTROL_EXCEPTION_HH_ +#define APP_CONTROL_EXCEPTION_HH_ + +#include +#include + +#include "app-control/log_private.hh" + +#define THROW(error_code) throw Exception(error_code, __FUNCTION__, __LINE__) + +namespace app_control { + +class Exception : public std::exception { + public: + explicit Exception(int error_code, std::string file = __FILE__, + int line = __LINE__ ) { + error_code_ = error_code; + message_ = file.substr(file.find_last_of("/") + 1) + ":" + + std::to_string(line) + " code:" + std::to_string(error_code_); + } + + virtual ~Exception() {} + + virtual const char *what(void) const noexcept { + return message_.c_str(); + } + + int GetErrorCode() { + return error_code_; + } + + private: + int error_code_; + std::string message_; +}; + +} // namespace app_control + +#endif // APP_CONTROL_EXCEPTION_HH_ diff --git a/src/app-control/launch_mode.hh b/src/app-control/launch_mode.hh new file mode 100644 index 0000000..7a89e47 --- /dev/null +++ b/src/app-control/launch_mode.hh @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_LAUNCH_MODE_HH_ +#define APP_CONTROL_LAUNCH_MODE_HH_ + +namespace app_control { + +enum LaunchMode : int { + Single, + Group, +}; + +} // namespace app_control + +#endif // APP_CONTROL_LAUNCH_MODE_HH_ diff --git a/src/app-control/log_private.hh b/src/app-control/log_private.hh new file mode 100644 index 0000000..65ffa06 --- /dev/null +++ b/src/app-control/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_LOG_PRIVATE_HH_ +#define APP_CONTROL_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "CAPI_APPFW_APP_CONTROL" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // APP_CONTROL_LOG_PRIVATE_HH_ diff --git a/src/app-control/pending_item.cc b/src/app-control/pending_item.cc new file mode 100644 index 0000000..37819d8 --- /dev/null +++ b/src/app-control/pending_item.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 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. + */ + +#include "app-control/pending_item.hh" + +namespace app_control { + +ReplyInfo::ReplyInfo(tizen_base::Bundle b, int result, void* data) + : b_(std::move(b)), result_(result), data_(data) { +} + +ReplyInfo::~ReplyInfo() = default; + +tizen_base::Bundle ReplyInfo::GetBundle() const { + return b_; +} + +int ReplyInfo::GetResult() const { + return result_; +} + +void* ReplyInfo::GetData() const { + return data_; +} + +ResultInfo::ResultInfo(int result, void* data) + : result_(result), data_(data) { +} + +ResultInfo::~ResultInfo() = default; + +int ResultInfo::GetResult() const { + return result_; +} + +void* ResultInfo::GetData() const { + return data_; +} + +PendingItem::PendingItem(int id) : id_(id) { +} + +PendingItem::~PendingItem() = default; + +int PendingItem::GetId() const { + return id_; +} + +void PendingItem::SetReplyInfo(std::shared_ptr reply_info) { + reply_info_ = std::move(reply_info); +} + +std::shared_ptr PendingItem::GetReplyInfo() const { + return reply_info_; +} + +void PendingItem::SetResultInfo(std::shared_ptr result_info) { + result_info_ = std::move(result_info); +} + +std::shared_ptr PendingItem::GetResultInfo() const { + return result_info_; +} + +} // namespace app_control diff --git a/src/app-control/pending_item.hh b/src/app-control/pending_item.hh new file mode 100644 index 0000000..20c79e9 --- /dev/null +++ b/src/app-control/pending_item.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_PENDING_ITEM_HH_ +#define APP_CONTROL_PENDING_ITEM_HH_ + +#include + +namespace app_control { + +class ReplyInfo { + public: + ReplyInfo(tizen_base::Bundle b, int result, void* data); + virtual ~ReplyInfo(); + + tizen_base::Bundle GetBundle() const; + int GetResult() const; + void* GetData() const; + + private: + tizen_base::Bundle b_; + int result_; + void* data_; +}; + +class ResultInfo { + public: + ResultInfo(int result, void* data); + virtual ~ResultInfo(); + + int GetResult() const; + void* GetData() const; + + private: + int result_; + void* data_; +}; + +class PendingItem { + public: + PendingItem(int id); + virtual ~PendingItem(); + + int GetId() const; + + void SetReplyInfo(std::shared_ptr reply_info); + std::shared_ptr GetReplyInfo() const; + + void SetResultInfo(std::shared_ptr result_info); + std::shared_ptr GetResultInfo() const; + + private: + int id_; + std::shared_ptr reply_info_; + std::shared_ptr result_info_; +}; + +} // namespace app_control + +#endif // APP_CONTROL_PENDING_ITEM_HH_ diff --git a/src/app-control/request_context.cc b/src/app-control/request_context.cc new file mode 100644 index 0000000..4a9f96d --- /dev/null +++ b/src/app-control/request_context.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 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. + */ + +#include + +#include "app-control/request_context.hh" + +namespace app_control { + +RequestContext::RequestContext(std::shared_ptr app_control, + app_control_result_cb result_cb, app_control_reply_cb reply_cb, + void* user_data) + : request_id_(GenerateId()), + app_control_(std::move(app_control)), + result_cb_(result_cb), + reply_cb_(reply_cb), + user_data_(user_data) { +} + +int RequestContext::GetRequestId() const { + return request_id_; +} + +std::shared_ptr RequestContext::GetAppControl() const { + return app_control_; +} + +app_control_result_cb RequestContext::GetResultCb() const { + return result_cb_; +} + +app_control_reply_cb RequestContext::GetReplyCb() const { + return reply_cb_; +} + +void* RequestContext::GetUserData() const { + return user_data_; +} + +int RequestContext::GenerateId() { + static std::atomic id { 0 }; + if (id + 1 < 0) + id.exchange(0); + + return ++id; +} + +} // namespace app_control diff --git a/src/app-control/request_context.hh b/src/app-control/request_context.hh new file mode 100644 index 0000000..852095f --- /dev/null +++ b/src/app-control/request_context.hh @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_REQUEST_CONTEXT_HH_ +#define APP_CONTROL_REQUEST_CONTEXT_HH_ + +#include + +#include "app-control/app_control.hh" +#include "include/app_control.h" + +namespace app_control { + +class RequestContext { + public: + RequestContext(std::shared_ptr app_control, + app_control_result_cb result_cb, app_control_reply_cb reply_cb, + void* user_data); + + int GetRequestId() const; + std::shared_ptr GetAppControl() const; + app_control_result_cb GetResultCb() const; + app_control_reply_cb GetReplyCb() const; + void* GetUserData() const; + + static int GenerateId(); + + private: + int request_id_; + std::shared_ptr app_control_; + app_control_result_cb result_cb_; + app_control_reply_cb reply_cb_; + void* user_data_; +}; + +} // namespace app_control + +#endif // APP_CONTROL_REQUEST_CONTEXT_HH_ diff --git a/src/app-control/result.hh b/src/app-control/result.hh new file mode 100644 index 0000000..df423da --- /dev/null +++ b/src/app-control/result.hh @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_RESULT_HH_ +#define APP_CONTROL_RESULT_HH_ + +namespace app_control { + +enum Result : int { + AppStarted = 1, + Succeeded = 0, + Failed = -1, + Canceled = -2, +}; + +} // namespace app_control + +#endif // APP_CONTROL_RESULT_HH_ diff --git a/src/app-control/stub.cc b/src/app-control/stub.cc new file mode 100644 index 0000000..4dc0081 --- /dev/null +++ b/src/app-control/stub.cc @@ -0,0 +1,1215 @@ +/* + * Copyright (c) 2021 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "app-control/app_control.hh" +#include "app-control/app_control_action.hh" +#include "app-control/app_control_broker.hh" +#include "app-control/exception.hh" +#include "app-control/log_private.hh" +#include "app-control/util.hh" +#include "include/app_control.h" +#include "include/app_control_internal.h" + +#undef EXPORT +#define EXPORT extern "C" __attribute__((visibility("default"))) + +#undef DEPRECATION_WARNING +#define DEPRECATION_WARNING() do { \ + dlog_print(DLOG_WARN, LOG_TAG, \ + "DEPRECATION WARNING: %s() is deprecated and " \ + "will be removed from next release.", __FUNCTION__); \ +} while (0) + +using namespace app_control; + +namespace { + +class ActionExt : public AppControlAction, + public AppControlAction::IEvent { + public: + ActionExt(std::string action) : AppControlAction(action, this) { + } + + virtual ~ActionExt() { + } + + void SetActionCb(app_control_action_cb cb, void* user_data) { + cb_ = cb; + user_data_ = user_data; + } + + private: + void OnAction(const std::string& action, bundle* data) override { + app_control_h app_control; + int ret = app_control_create_event(data, &app_control); + if (ret != APP_CONTROL_ERROR_NONE) { + _E("Failed to create app-control handle. error(%d)", ret); + return; + } + + cb_(action.c_str(), app_control, user_data_); + app_control_destroy(app_control); + } + + private: + app_control_action_cb cb_; + void* user_data_; +}; + +} // namespace + +EXPORT int app_control_create_request(bundle* data, + app_control_h* app_control) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + tizen_base::Bundle b; + if (data != nullptr) + b = tizen_base::Bundle(data, true, true); + + auto* handle = new (std::nothrow) AppControl(b); + if (handle == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + + *app_control = static_cast(handle); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_create(app_control_h* app_control) { + return app_control_create_request(nullptr, app_control); +} + +EXPORT int app_control_create_with_parameters(app_control_h* app_control, + const char* operation, const char* uri, const char* mime, + const char* category, const char* app_id, app_control_launch_mode_e mode, + int extra_data_count, ...) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + app_control_h handle; + int ret = app_control_create(&handle); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + auto ptr = std::unique_ptr::type, + decltype(app_control_destroy)*>(handle, app_control_destroy); + + if (operation != nullptr) { + ret = app_control_set_operation(handle, operation); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + } + + if (uri != nullptr) { + ret = app_control_set_uri(handle, uri); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + } + + if (mime != nullptr) { + ret = app_control_set_mime(handle, mime); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + } + + if (category != nullptr) { + ret = app_control_set_category(handle, category); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + } + + if (app_id != nullptr) { + ret = app_control_set_app_id(handle, app_id); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + } + + ret = app_control_set_launch_mode(handle, mode); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + va_list vl; + va_start(vl, extra_data_count); + for (int i = 0; i < extra_data_count; ++i) { + char* key = va_arg(vl, char*); + char* value = va_arg(vl, char*); + ret = app_control_add_extra_data(handle, key, value); + if (ret != APP_CONTROL_ERROR_NONE) { + va_end(vl); + return ret; + } + } + va_end(vl); + + *app_control = ptr.release(); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_create_from_uri_handle(app_control_h* app_control, + app_control_uri_h uri) { + if (app_control == nullptr || uri == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + app_control_h handle; + int ret = app_control_create(&handle); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + auto ptr = std::unique_ptr::type, + decltype(app_control_destroy)*>(handle, app_control_destroy); + + ret = app_control_set_operation(handle, APP_CONTROL_OPERATION_INTENT); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + ret = app_control_set_uri_by_handle(handle, uri); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + const char* path; + ret = app_control_uri_get_path(uri, &path); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + ret = app_control_add_extra_data(handle, APP_CONTROL_DATA_URI_PATH, path); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + const char* fragment; + ret = app_control_uri_get_fragment(uri, &fragment); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + ret = app_control_add_extra_data(handle, APP_CONTROL_DATA_URI_FRAGMENT, + fragment); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + app_control_uri_query_h query; + ret = app_control_uri_get_query(uri, &query); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + ret = app_control_uri_query_foreach(query, + [](const char* key, const char* value, void* user_data) -> bool { + auto* handle = static_cast(user_data); + int ret = app_control_add_extra_data(handle, key, value); + if (ret != APP_CONTROL_ERROR_NONE) { + _E("app_control_add_extra_data(%p, %s, %s) is failed. error(%d)", + handle, key, value, ret); + return false; + } + + return true; + }, handle); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + *app_control = ptr.release(); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_create_event(bundle* data, + app_control_h* app_control) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + tizen_base::Bundle b(data, true, true); + auto* handle = new (std::nothrow) AppControl(b, AppControl::Type::Event); + if (handle == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + + try { + std::string operation = handle->GetOperation(); + } catch (Exception& e) { + handle->SetOperation(APP_CONTROL_OPERATION_DEFAULT); + } + + *app_control = static_cast(handle); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_destroy(app_control_h app_control) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + delete handle; + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_to_bundle(app_control_h app_control, bundle** data) { + if (app_control == nullptr || data == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + *data = handle->ToBundle(); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_operation(app_control_h app_control, + const char* operation) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (operation != nullptr) { + try { + handle->SetOperation(operation); + } catch (Exception& e) { + _E("Invalid operation"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + } else { + handle->RemoveOperation(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_operation(app_control_h app_control, + char** operation) { + if (app_control == nullptr || operation == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetOperation(); + *operation = strdup(value.c_str()); + if (*operation == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *operation = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_uri(app_control_h app_control, const char* uri) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (uri != nullptr) { + try { + handle->SetUri(uri); + } catch (Exception& e) { + _E("Invalid uri"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + } else { + handle->RemoveUri(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_uri(app_control_h app_control, char** uri) { + if (app_control == nullptr || uri == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetUri(); + *uri = strdup(value.c_str()); + if (*uri == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *uri = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_uri_by_handle(app_control_h app_control, + app_control_uri_h uri) { + if (app_control == nullptr || uri == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + const char* scheme; + int ret = app_control_uri_get_scheme(uri, &scheme); + if (ret != APP_CONTROL_ERROR_NONE) + return APP_CONTROL_ERROR_INVALID_PARAMETER; + + const char* authority; + ret = app_control_uri_get_authority(uri, &authority); + if (ret != APP_CONTROL_ERROR_NONE) + return APP_CONTROL_ERROR_INVALID_PARAMETER; + + std::string uri_str = std::string(scheme) + ":" + std::string(authority); + ret = app_control_set_uri(app_control, uri_str.c_str()); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_mime(app_control_h app_control, const char* mime) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (mime != nullptr) { + try { + handle->SetMime(mime); + } catch (Exception& e) { + _E("Invalid MIME Type"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + } else { + handle->RemoveMime(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_mime(app_control_h app_control, char** mime) { + if (app_control == nullptr || mime == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetMime(); + *mime = strdup(value.c_str()); + if (*mime == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *mime = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_category(app_control_h app_control, + const char* category) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (category != nullptr) { + try { + handle->SetCategory(category); + } catch (Exception& e) { + _E("Invalid category"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + } else { + handle->RemoveCategory(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_category(app_control_h app_control, + char** category) { + if (app_control == nullptr || category == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetCategory(); + *category = strdup(value.c_str()); + if (*category == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *category = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_app_id(app_control_h app_control, + const char* app_id) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (app_id != nullptr) { + try { + handle->SetAppId(app_id); + } catch (Exception& e) { + _E("Invalid application ID"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + } else { + handle->RemoveAppId(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_app_id(app_control_h app_control, char** app_id) { + if (app_control == nullptr || app_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetAppId(); + *app_id = strdup(value.c_str()); + if (*app_id == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *app_id = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_clone(app_control_h* clone, app_control_h app_control) { + if (clone == nullptr || app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* control = static_cast(app_control); + auto* handle = new (std::nothrow) AppControl(*control); + if (handle == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + + *clone = static_cast(handle); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_launch_mode(app_control_h app_control, + app_control_launch_mode_e mode) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (mode != APP_CONTROL_LAUNCH_MODE_SINGLE && + mode != APP_CONTROL_LAUNCH_MODE_GROUP) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + LaunchMode launch_mode = (mode == APP_CONTROL_LAUNCH_MODE_SINGLE) ? + LaunchMode::Single : LaunchMode::Group; + auto* handle = static_cast(app_control); + handle->SetLaunchMode(launch_mode); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_launch_mode(app_control_h app_control, + app_control_launch_mode_e* mode) { + if (app_control == nullptr || mode == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + LaunchMode launch_mode = handle->GetLaunchMode(); + if (launch_mode == LaunchMode::Group) + *mode = APP_CONTROL_LAUNCH_MODE_GROUP; + else + *mode = APP_CONTROL_LAUNCH_MODE_SINGLE; + } catch (Exception& e) { + _W("Launch mode is not matched"); + *mode = APP_CONTROL_LAUNCH_MODE_SINGLE; + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_defapp(app_control_h app_control, + const char* app_id) { + if (app_control == nullptr || app_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + int ret = app_control_set_app_id(app_control, app_id); + if (ret != APP_CONTROL_ERROR_NONE) + return ret; + + auto* handle = static_cast(app_control); + ret = aul_set_default_app_by_operation(handle->ToBundle()); + if (ret != AUL_R_OK) { + _E("Failed to set default application. app_id(%s), error(%d)", app_id, ret); + if (ret == AUL_R_EILLACC) + return APP_CONTROL_ERROR_PERMISSION_DENIED; + + return APP_CONTROL_ERROR_IO_ERROR; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_unset_defapp(const char* app_id) { + if (app_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + int ret = aul_unset_default_app_by_operation(app_id); + if (ret != AUL_R_OK) { + _E("Failed to unset default application. app_id(%s), error(%d)", + app_id, ret); + if (ret == AUL_R_EILLACC) + return APP_CONTROL_ERROR_PERMISSION_DENIED; + + return APP_CONTROL_ERROR_IO_ERROR; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_add_extra_data(app_control_h app_control, + const char* key, const char* value) { + if (app_control == nullptr || key == nullptr || value == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + try { + handle->AddExtraData(key, value); + } catch (Exception& e) { + _E("Failed to add extra data. error(%d)", e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_add_extra_data_array(app_control_h app_control, + const char* key, const char* value[], int length) { + if (app_control == nullptr || key == nullptr || + value == nullptr || length <= 0) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::vector values(value, value + length); + handle->AddExtraDataArray(key, values); + } catch (Exception& e) { + _E("Failed to add extra data array. error(%d)", e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_remove_extra_data(app_control_h app_control, + const char* key) { + if (app_control == nullptr || key == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + handle->RemoveExtraData(key); + } catch (Exception& e) { + _E("Failed to remove extra data. error(%d)", e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_extra_data(app_control_h app_control, + const char* key, char** value) { + if (app_control == nullptr || key == nullptr || value == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string extra_data = handle->GetExtraData(key); + *value = strdup(extra_data.c_str()); + if (*value == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + _E("Failed to get extra data. error(%d)", e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_extra_data_array(app_control_h app_control, + const char* key, char*** value, int* length) { + if (app_control == nullptr || key == nullptr || + value == nullptr || length == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + char** array_data = nullptr; + int array_data_length = 0; + try { + auto* handle = static_cast(app_control); + std::vector values = handle->GetExtraDataArray(key); + array_data = reinterpret_cast(calloc(values.size(), sizeof(char*))); + if (array_data == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + + array_data_length = values.size(); + for (int i = 0; i < array_data_length; ++i) + array_data[i] = strdup(values[i].c_str()); + } catch (Exception& e) { + _E("Failed to get extra data array. error(%d)", e.GetErrorCode()); + return e.GetErrorCode(); + } + + *value = array_data; + *length = array_data_length; + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_is_extra_data_array(app_control_h app_control, + const char* key, bool* array) { + if (app_control == nullptr || key == nullptr || array == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + *array = handle->IsExtraDataArray(key); + } catch (Exception& e) { + _E("Failed to check whether the data is array or not. key(%s), error(%d)", + key, e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_foreach_extra_data(app_control_h app_control, + app_control_extra_data_cb callback, void* user_data) { + if (app_control == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + for (auto& key : handle->GetExtraDataKeys()) { + if (!callback(app_control, key.c_str(), user_data)) + break; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_foreach_app_matched(app_control_h app_control, + app_control_app_matched_cb callback, void* user_data) { + if (app_control == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + for (auto& app_id : handle->GetMatchedAppIds()) { + if (!callback(app_control, app_id.c_str(), user_data)) + break; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_caller(app_control_h app_control, char** app_id) { + if (app_control == nullptr || app_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string caller = handle->GetCaller(); + *app_id = strdup(caller.c_str()); + if (*app_id == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + _E("Failed to find caller appid. error(%d)", e.GetErrorCode()); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_is_reply_requested(app_control_h app_control, + bool* requested) { + if (app_control == nullptr || requested == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + *requested = handle->IsReplyRequested(); + } catch (Exception& e) { + _E("Invalid app-control handle"); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_import_from_bundle(app_control_h app_control, + bundle* data) { + if (app_control == nullptr || data == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + tizen_base::Bundle b(data, true, true); + handle->SetBundle(b); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_export_as_bundle(app_control_h app_control, + bundle** data) { + if (app_control == nullptr || data == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + auto* b = handle->ToBundle(); + *data = bundle_dup(b); + if (*data == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_enable_app_started_result_event( + app_control_h app_control) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + handle->EnableAppStartedResultEvent(); + } catch (Exception& e) { + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_instance_id(app_control_h app_control, + const char* instance_id) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (instance_id != nullptr) { + try { + handle->SetInstanceId(instance_id); + } catch (Exception& e) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } else { + handle->RemoveInstanceId(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_instance_id(app_control_h app_control, + char** instance_id) { + if (app_control == nullptr || instance_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetInstanceId(); + *instance_id = strdup(value.c_str()); + if (*instance_id == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + _E("Failed to get instance ID"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_add_action_handler(const char* action, + app_control_action_cb callback, void* user_data, + app_control_action_h* handle) { + if (action == nullptr || callback == nullptr || handle == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + ActionExt* p = nullptr; + try { + p = new (std::nothrow) ActionExt(action); + } catch (Exception& e) { + _E("Failed to create action handle. action(%s), error(%d)", + action, e.GetErrorCode()); + return e.GetErrorCode(); + } + + p->SetActionCb(callback, user_data); + *handle = static_cast(p); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_remove_action_handler(app_control_action_h handle) { + if (handle == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* p = static_cast(handle); + delete p; + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_caller_instance_id(app_control_h app_control, + const char* instance_id) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (instance_id != nullptr) { + try { + handle->SetCallerInstanceId(instance_id); + } catch (Exception& e) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } else { + handle->RemoveCallerInstanceId(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_component_id(app_control_h app_control, + const char* component_id) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (component_id != nullptr) { + try { + handle->SetComponentId(component_id); + } catch (Exception& e) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } else { + handle->RemoveComponentId(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_component_id(app_control_h app_control, + char** component_id) { + if (app_control == nullptr || component_id == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + std::string value = handle->GetComponentId(); + *component_id = strdup(value.c_str()); + if (*component_id == nullptr) { + _E("Out of memory"); + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + } + } catch (Exception& e) { + *component_id = nullptr; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_prepare_app_defined_loader(app_control_h app_control, + const char* loader_name) { + if (app_control == nullptr || loader_name == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + int loader_id = aul_prepare_app_defined_loader(loader_name); + if (loader_id < 0) { + _E("Failed to prepare app defined loader. loader_name(%s), error(%d)", + loader_name, loader_id); + return Util::AulErrorConvert(loader_id); + } + + try { + auto* handle = static_cast(app_control); + handle->SetAppDefinedLoader(loader_name); + handle->SetLoaderId(loader_id); + } catch (Exception& e) { + _E("Failed to set loader id. loader_id(%s), error(%d)", + loader_name, e.GetErrorCode()); + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_send_terminate_request(app_control_h app_control) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(app_control); + if (handle->GetType() != AppControl::Type::Request || + handle->GetLaunchedPid() < 0) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + aul_svc_subapp_terminate_request(handle->ToBundle(), + handle->GetLaunchedPid()); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_reply_to_launch_request(app_control_h reply, + app_control_h request, app_control_result_e result) { + if (reply == nullptr || request ==nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (result == APP_CONTROL_RESULT_APP_STARTED) { + _E("APP_CONTROL_RESULT_APP_STARTED is not allowed"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + auto* handle = static_cast(request); + bundle* reply_data; + int ret = aul_svc_create_result_bundle(handle->ToBundle(), &reply_data); + if (ret != AUL_SVC_RET_OK) { + if (ret == AUL_SVC_RET_ECANCELED) + return APP_CONTROL_ERROR_NONE; + + _E("Failed to create a result bundle"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + AppControl app_control(tizen_base::Bundle(reply_data, false, true)); + auto* reply_handle = static_cast(reply); + for (auto& key : reply_handle->GetExtraDataKeys()) { + if (reply_handle->IsExtraDataArray(key)) { + app_control.AddExtraDataArray(key, reply_handle->GetExtraDataArray(key)); + } else { + app_control.AddExtraData(key, reply_handle->GetExtraData(key)); + } + } + + ret = aul_svc_send_result(app_control.ToBundle(), + Util::AppControlResultConvert(result)); + if (ret != AUL_SVC_RET_OK) { + if (ret == AUL_SVC_RET_EINVAL) + return APP_CONTROL_ERROR_INVALID_PARAMETER; + + return APP_CONTROL_ERROR_LAUNCH_REJECTED; + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_send_launch_request(app_control_h app_control, + app_control_reply_cb callback, void* user_data) { + if (app_control == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + auto request_context = std::make_shared( + std::shared_ptr(new AppControl(*handle)), + nullptr, callback, user_data); + auto* broker = AppControlBroker::GetInst(); + broker->SendLaunchRequest(handle, request_context); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_send_launch_request_async(app_control_h app_control, + app_control_result_cb result_cb, app_control_reply_cb reply_cb, + void* user_data) { + if (app_control == nullptr || result_cb == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + auto request_context = std::make_shared( + std::shared_ptr(new AppControl(*handle)), + result_cb, reply_cb, user_data); + auto* broker = AppControlBroker::GetInst(); + broker->SendLaunchRequest(handle, request_context); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_send_launch_request_sync(app_control_h app_control, + app_control_h* reply, app_control_result_e* result) { + if (app_control == nullptr || reply == nullptr || result == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + AppControl* reply_handle = nullptr; + auto* handle = static_cast(app_control); + auto* broker = AppControlBroker::GetInst(); + broker->SendLaunchRequest(handle, &reply_handle, result); + *reply = static_cast(reply_handle); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_send_resume_request(app_control_h app_control, + app_control_result_cb result_cb, void* user_data) { + if (app_control == nullptr || result_cb == nullptr) { + _E("Invalid parameter"); + return APP_CONTROL_ERROR_INVALID_PARAMETER; + } + + try { + auto* handle = static_cast(app_control); + auto request_context = std::make_shared( + std::shared_ptr(new AppControl(*handle)), + result_cb, nullptr, user_data); + auto* broker = AppControlBroker::GetInst(); + broker->SendResumeRequest(handle, request_context); + } catch (Exception& e) { + return e.GetErrorCode(); + } + + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_set_window(app_control_h app_control, unsigned int id) { + DEPRECATION_WARNING(); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_get_window(app_control_h app_control, unsigned int* id) { + DEPRECATION_WARNING(); + return APP_CONTROL_ERROR_NONE; +} + +EXPORT int app_control_request_transient_app(app_control_h app_control, + unsigned int callee_id, app_control_host_res_fn cbfunc, void* data) { + DEPRECATION_WARNING(); + return APP_CONTROL_ERROR_NONE; +} + diff --git a/src/app-control/util.cc b/src/app-control/util.cc new file mode 100644 index 0000000..5d980cf --- /dev/null +++ b/src/app-control/util.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 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. + */ + +#include "app-control/util.hh" + +namespace app_control { + +int Util::AulErrorConvert(int ret) { + switch (ret) { + case AUL_R_EINVAL: + return APP_CONTROL_ERROR_INVALID_PARAMETER; + case AUL_R_ENOMEM: + return APP_CONTROL_ERROR_OUT_OF_MEMORY; + case AUL_R_EILLACC: + return APP_CONTROL_ERROR_PERMISSION_DENIED; + default: + return APP_CONTROL_ERROR_IO_ERROR; + } +} + +app_control_result_e Util::AulSvcResultConvert(aul_svc_result_val result) { + switch (result) { + case AUL_SVC_RES_OK: + return APP_CONTROL_RESULT_SUCCEEDED; + case AUL_SVC_RES_NOT_OK: + return APP_CONTROL_RESULT_FAILED; + default: + return APP_CONTROL_RESULT_CANCELED; + } +} + +aul_svc_result_val Util::AppControlResultConvert(app_control_result_e result) { + switch (result) { + case APP_CONTROL_RESULT_SUCCEEDED: + return AUL_SVC_RES_OK; + case APP_CONTROL_RESULT_FAILED: + return AUL_SVC_RES_NOT_OK; + default: + return AUL_SVC_RES_CANCEL; + } +} + +int Util::AulSvcErrorConvert(int res) { + switch (res) { + case AUL_SVC_RET_OK: + return APP_CONTROL_ERROR_NONE; + case AUL_SVC_RET_ENOMATCH: + return APP_CONTROL_ERROR_APP_NOT_FOUND; + case AUL_SVC_RET_EILLACC: + return APP_CONTROL_ERROR_PERMISSION_DENIED; + case AUL_SVC_RET_EINVAL: + return APP_CONTROL_ERROR_INVALID_PARAMETER; + default: + return APP_CONTROL_ERROR_LAUNCH_REJECTED; + } +} + +} // namespace app_control diff --git a/src/app-control/util.hh b/src/app-control/util.hh new file mode 100644 index 0000000..e252ac2 --- /dev/null +++ b/src/app-control/util.hh @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 APP_CONTROL_UTIL_HH_ +#define APP_CONTROL_UTIL_HH_ + +#include +#include +#include + +#include "include/app_control.h" + +namespace app_control { + +class Util { + public: + static int AulErrorConvert(int ret); + static app_control_result_e AulSvcResultConvert(aul_svc_result_val result); + static aul_svc_result_val AppControlResultConvert( + app_control_result_e result); + static int AulSvcErrorConvert(int res); +}; + +} // namespace app_control + +#endif // APP_CONTROL_UTIL_HH_ diff --git a/test/unit_tests/app_control_unittest.cc b/test/unit_tests/app_control_unittest.cc index 3bfbd19..bb01752 100644 --- a/test/unit_tests/app_control_unittest.cc +++ b/test/unit_tests/app_control_unittest.cc @@ -141,9 +141,11 @@ int fake_aul_svc_send_result_AUL_SVC_RET_ERROR(bundle* b, return AUL_SVC_RET_ERROR; } -int fake_aul_svc_get_list_for_uid_AUL_SVC_RET_OK(bundle* b, - aul_svc_info_iter_fn iter_fn, void* data, uid_t uid) { - iter_fn("org.example.call", data); +int fake_aul_svc_get_appid_array_AUL_SVC_RET_OK(bundle* b, + uid_t uid, char*** appid_array, unsigned int* len) { + *appid_array = reinterpret_cast(calloc(1, sizeof(char*))); + (*appid_array)[0] = strdup("org.example.call"); + *len = 1; return AUL_SVC_RET_OK; } @@ -1145,8 +1147,8 @@ TEST_F(AppControlTest, app_control_foreach_app_matched_P) { app_control_set_operation(app_control_, APP_CONTROL_OPERATION_CALL); app_control_set_uri(app_control_, "tel:010-2345-6789"); - EXPECT_CALL(GetMock(), aul_svc_get_list_for_uid(_, _, _, _)). - WillOnce(Invoke(fake_aul_svc_get_list_for_uid_AUL_SVC_RET_OK)); + EXPECT_CALL(GetMock(), aul_svc_get_appid_array(_, _, _, _)). + WillOnce(Invoke(fake_aul_svc_get_appid_array_AUL_SVC_RET_OK)); bool touch = false; int ret = app_control_foreach_app_matched(app_control_, diff --git a/test/unit_tests/mock/aul_mock.cc b/test/unit_tests/mock/aul_mock.cc index a534066..0d7524a 100644 --- a/test/unit_tests/mock/aul_mock.cc +++ b/test/unit_tests/mock/aul_mock.cc @@ -51,9 +51,10 @@ extern "C" int aul_svc_send_result(bundle* b, aul_svc_result_val result) { return MOCK_HOOK_P2(AulMock, aul_svc_send_result, b, result); } -extern "C" int aul_svc_get_list_for_uid(bundle* b, aul_svc_info_iter_fn iter_fn, - void* data, uid_t uid) { - return MOCK_HOOK_P4(AulMock, aul_svc_get_list_for_uid, b, iter_fn, data, uid); +extern "C" int aul_svc_get_appid_array(bundle* b, uid_t uid, + char*** appid_array, unsigned int* len) { + return MOCK_HOOK_P4(AulMock, aul_svc_get_appid_array, b, uid, appid_array, + len); } extern "C" int aul_svc_send_launch_request_sync_for_uid(bundle* b, int id, diff --git a/test/unit_tests/mock/aul_mock.hh b/test/unit_tests/mock/aul_mock.hh index 73e86b9..2a3912d 100644 --- a/test/unit_tests/mock/aul_mock.hh +++ b/test/unit_tests/mock/aul_mock.hh @@ -37,8 +37,8 @@ class AulMock : public virtual ModuleMock { MOCK_METHOD2(aul_svc_subapp_terminate_request, int (bundle*, int)); MOCK_METHOD2(aul_svc_create_result_bundle, int (bundle*, bundle**)); MOCK_METHOD2(aul_svc_send_result, int (bundle*, aul_svc_result_val)); - MOCK_METHOD4(aul_svc_get_list_for_uid, - int (bundle*, aul_svc_info_iter_fn, void*, uid_t)); + MOCK_METHOD4(aul_svc_get_appid_array, + int (bundle*, uid_t, char***, unsigned int *)); MOCK_METHOD5(aul_svc_send_launch_request_sync_for_uid, int (bundle*, int, bundle**, aul_svc_result_val*, uid_t)); MOCK_METHOD5(aul_svc_send_resume_request_for_uid, -- 2.34.1