From: Hwankyu Jhun Date: Mon, 9 Nov 2020 00:56:58 +0000 (+0900) Subject: Fix CMake configuration file X-Git-Tag: submit/tizen/20201125.065114~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1d4e0b4e93f7e7770aaf83a122f16ccd4fa0f1d7;p=platform%2Fcore%2Fapi%2Fapp-control.git Fix CMake configuration file Change-Id: Ib9ff75e82d14111eea6befeea06e1eafda3e9dfd Signed-off-by: Hwankyu Jhun --- diff --git a/CMakeLists.txt b/CMakeLists.txt index cfb1bde..1317f08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,54 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(INC_DIR include) +PROJECT(capi-appfw-app-control) -ADD_SUBDIRECTORY(src) +SET(CMAKE_INSTALL_PREFIX /usr) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(PC_NAME "capi-appfw-app-control") +SET(PC_REQUIRED "capi-base-common") +SET(PC_LDFLAGS "-lcapi-appfw-app-control -lcapi-appfw-app-control-uri") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-zdefs") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} -std=c++14") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") + +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") -INSTALL( - DIRECTORY ${INC_DIR}/ DESTINATION include/appfw - FILES_MATCHING - PATTERN "*_private.h" EXCLUDE - PATTERN "${INC_DIR}/*.h" - ) +SET(TARGET_APP_CONTROL "capi-appfw-app-control") +SET(TARGET_APP_CONTROL_URI "capi-appfw-app-control-uri") -IF(NOT DEFINED MINIMUM_BUILD) ENABLE_TESTING() -SET(UNITTESTS appctrl_unittests) -ADD_TEST(NAME ${UNITTESTS} COMMAND ${UNITTESTS} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unit_tests) +SET(TARGET_APP_CONTROL_UNIT_TEST "app-control-unit-test") -ADD_SUBDIRECTORY(unit_tests) -ENDIF(NOT DEFINED MINIMUM_BUILD) +INCLUDE(FindPkgConfig) +INCLUDE(ApplyPkgConfig) + +PKG_CHECK_MODULES(APPCORE_COMMON_DEPS REQUIRED appcore-common) +PKG_CHECK_MODULES(AUL_DEPS REQUIRED aul) +PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle) +PKG_CHECK_MODULES(CAPI_BASE_COMMON_DEPS REQUIRED capi-base-common) +PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog) +PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0) +PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) + +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/${TARGET_APP_CONTROL}.pc.in + ${CMAKE_SOURCE_DIR}/${TARGET_APP_CONTROL}.pc @ONLY) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/${TARGET_APP_CONTROL}.pc DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw + FILES_MATCHING + PATTERN "*_private.h" EXCLUDE + PATTERN "include/*.h" +) + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(test) diff --git a/cmake/Modules/ApplyPkgConfig.cmake b/cmake/Modules/ApplyPkgConfig.cmake new file mode 100644 index 0000000..9b84be3 --- /dev/null +++ b/cmake/Modules/ApplyPkgConfig.cmake @@ -0,0 +1,35 @@ +# Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# +# This function applies external (out of source tree) dependencies +# to given target. Arguments are: +# TARGET - valid cmake target +# PRIVACY - dependency can be inherited by dependent targets or not: +# PUBLIC - this should be used by default, cause compile/link flags passing +# PRIVATE - do not passes any settings to dependent targets, +# may be usefull for static libraries from the inside of the project +# Argument ARGV2 and following are supposed to be names of checked pkg config +# packages. This function will use variables created by check_pkg_modules(). +# - ${DEP_NAME}_LIBRARIES +# - ${DEP_NAME}_INCLUDE_DIRS +# - ${DEP_NAME}_CFLAGS +# +FUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) + MATH(EXPR DEST_INDEX "${ARGC}-1") + FOREACH(I RANGE 2 ${DEST_INDEX}) + IF(NOT ${ARGV${I}}_FOUND) + MESSAGE(FATAL_ERROR "Not found dependency - ${ARGV${I}}_FOUND") + ENDIF(NOT ${ARGV${I}}_FOUND) + TARGET_LINK_LIBRARIES(${TARGET} ${PRIVACY} "${${ARGV${I}}_LIBRARIES}") + TARGET_INCLUDE_DIRECTORIES(${TARGET} ${PRIVACY} SYSTEM "${${ARGV${I}}_INCLUDE_DIRS}") + STRING(REPLACE ";" " " CFLAGS_STR "${${ARGV${I}}_CFLAGS}") + SET(CFLAGS_LIST ${CFLAGS_STR}) + SEPARATE_ARGUMENTS(CFLAGS_LIST) + FOREACH(OPTION ${CFLAGS_LIST}) + TARGET_COMPILE_OPTIONS(${TARGET} ${PRIVACY} ${OPTION}) + ENDFOREACH(OPTION) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES SKIP_BUILD_RPATH true) + ENDFOREACH(I RANGE 2 ${DEST_INDEX}) +ENDFUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) diff --git a/packaging/capi-appfw-app-control.spec b/packaging/capi-appfw-app-control.spec index b7d699d..7f1efd9 100644 --- a/packaging/capi-appfw-app-control.spec +++ b/packaging/capi-appfw-app-control.spec @@ -120,7 +120,7 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj # unittests ################################################# %files unittests -%{_bindir}/appctrl_unittests +%{_bindir}/app-control-unit-test ################################################# # uri-gcov diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f3cdc7..246e0e8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,67 +1,2 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -SET(fw_name "capi-appfw-app-control") -SET(uri_fw_name "capi-appfw-app-control-uri") - -PROJECT(${fw_name}) - -SET(CMAKE_INSTALL_PREFIX /usr) -SET(PREFIX ${CMAKE_INSTALL_PREFIX}) - -SET(INC_DIR ${CMAKE_SOURCE_DIR}/include) -INCLUDE_DIRECTORIES(${INC_DIR}) - -SET(requires "dlog bundle aul capi-base-common appcore-common") -SET(pc_requires "capi-base-common") - -INCLUDE(FindPkgConfig) -pkg_check_modules(${fw_name} REQUIRED ${requires}) -FOREACH(flag ${${fw_name}_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror") -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") - -IF("${ARCH}" STREQUAL "arm") - ADD_DEFINITIONS("-DTARGET") -ENDIF("${ARCH}" STREQUAL "arm") - -ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") -ADD_DEFINITIONS("-DSLP_DEBUG") - -SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") - -add_library(${fw_name} SHARED - app_control.c - ) - -TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS} ${uri_fw_name}) - -SET_TARGET_PROPERTIES(${fw_name} - PROPERTIES - VERSION ${FULLVER} - SOVERSION ${MAJORVER} - CLEAN_DIRECT_OUTPUT 1 -) - -INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR}) -INSTALL( - DIRECTORY ${INC_DIR}/ DESTINATION include/appfw - FILES_MATCHING - PATTERN "*_private.h" EXCLUDE - PATTERN "${INC_DIR}/*.h" - ) - - -SET(PC_NAME ${fw_name}) -SET(PC_REQUIRED ${pc_requires}) -SET(PC_LDFLAGS "-l${fw_name} -l${uri_fw_name}") - -CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/${fw_name}.pc.in - ${CMAKE_SOURCE_DIR}/${fw_name}.pc - @ONLY -) -INSTALL(FILES ${CMAKE_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) - +ADD_SUBDIRECTORY(app-control) ADD_SUBDIRECTORY(uri) diff --git a/src/app-control/CMakeLists.txt b/src/app-control/CMakeLists.txt new file mode 100644 index 0000000..b478318 --- /dev/null +++ b/src/app-control/CMakeLists.txt @@ -0,0 +1,22 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CONTROL_SRCS) + +ADD_LIBRARY(${TARGET_APP_CONTROL} SHARED ${APP_CONTROL_SRCS}) +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}/../../include) + +APPLY_PKG_CONFIG(${TARGET_APP_CONTROL} PUBLIC + APPCORE_COMMON_DEPS + AUL_DEPS + BUNDLE_DEPS + CAPI_BASE_COMMON_DEPS + DLOG_DEPS +) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CONTROL} PUBLIC + ${TARGET_APP_CONTROL_URI}) + +INSTALL(TARGETS ${TARGET_APP_CONTROL} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/app-control/app_control.c b/src/app-control/app_control.c new file mode 100644 index 0000000..3a9aaec --- /dev/null +++ b/src/app-control/app_control.c @@ -0,0 +1,2501 @@ +/* + * 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); + 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.c b/src/app_control.c deleted file mode 100644 index cf5fa55..0000000 --- a/src/app_control.c +++ /dev/null @@ -1,2498 +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])) - -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 */ - -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; -} - -int app_control_create(app_control_h *app_control) -{ - return app_control_create_request(NULL, app_control); -} - -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; -} - -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; -} - -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); - 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 */ - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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); -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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); -} - -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; -} - -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; -} - -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; -} - -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; -} - -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 */ - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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); -} - -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; - } -} - -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 */ - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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); -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; - } -} - -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/uri/CMakeLists.txt b/src/uri/CMakeLists.txt index 5fff10a..2f78aa2 100644 --- a/src/uri/CMakeLists.txt +++ b/src/uri/CMakeLists.txt @@ -1,33 +1,20 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(capi-appfw-app-control-uri C CXX) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CONTROL_URI_SRCS) -IF("${FULLVER}" STREQUAL "") - MESSAGE(FATAL_ERROR "VERSION is not defined") -ENDIF() -STRING(REGEX MATCH "^[0-9]+" VERSION_MAJOR ${FULLVER}) -IF("${VERSION_MAJOR}" STREQUAL "") - MESSAGE(FATAL_ERROR "can't get VERSION_MAJOR") -ENDIF() +ADD_LIBRARY(${TARGET_APP_CONTROL_URI} SHARED + ${APP_CONTROL_URI_SRCS}) +SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL_URI} PROPERTIES + SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL_URI} PROPERTIES + VERSION ${FULLVER}) -### Required packages -INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 dlog) -FOREACH(flag ${pkgs_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CONTROL_URI} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../include) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fvisibility=hidden -flto") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fvisibility=hidden -flto") +APPLY_PKG_CONFIG(${TARGET_APP_CONTROL_URI} PUBLIC + DLOG_DEPS + GLIB_DEPS +) -### Local include directories -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/uri) - -### Build -AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src/uri SRCS) -ADD_LIBRARY(capi-appfw-app-control-uri SHARED ${SRCS}) -SET_TARGET_PROPERTIES(capi-appfw-app-control-uri PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(capi-appfw-app-control-uri PROPERTIES VERSION "${FULLVER}") -MESSAGE(STATUS "Version from debian/changelog: ${FULLVER}, Major version: ${MAJORVER}") -TARGET_LINK_LIBRARIES(capi-appfw-app-control-uri ${pkgs_LDFLAGS}) - -INSTALL(TARGETS capi-appfw-app-control-uri DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(TARGETS ${TARGET_APP_CONTROL_URI} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..c90fac8 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +ADD_SUBDIRECTORY(unit_tests) diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt new file mode 100644 index 0000000..061cd4c --- /dev/null +++ b/test/unit_tests/CMakeLists.txt @@ -0,0 +1,26 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CONTROL_UNIT_TEST_SRCS) + +ADD_EXECUTABLE(${TARGET_APP_CONTROL_UNIT_TEST} + ${APP_CONTROL_UNIT_TEST_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CONTROL_UNIT_TEST} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../ + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/app-control + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/uri) + +APPLY_PKG_CONFIG(${TARGET_APP_CONTROL_UNIT_TEST} PUBLIC + APPCORE_COMMON_DEPS + AUL_DEPS + GLIB_DEPS + GMOCK_DEPS +) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CONTROL_UNIT_TEST} PUBLIC + ${TARGET_APP_CONTROL} + ${TARGET_APP_CONTROL_URI}) +SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL_TESTS} PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${TARGET_APP_CONTROL_TESTS} PROPERTIES LINK_FLAGS "-pie") + +INSTALL(TARGETS ${TARGET_APP_CONTROL_UNIT_TEST} DESTINATION bin) diff --git a/test/unit_tests/app_control_unittest.cc b/test/unit_tests/app_control_unittest.cc new file mode 100644 index 0000000..23964a0 --- /dev/null +++ b/test/unit_tests/app_control_unittest.cc @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019 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. + */ + +#include +#include + +#include +#include + +#include "include/app_control.h" +#include "include/app_control_uri.h" +#include "src/uri/uri_internal.h" + +// The source of the following example is "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier" +static const char EXAM_URI1[] = "https://john.doe@www.example.com:123"; +extern int gargc; +extern char** gargv; + +class AppControlTest : public testing::Test { + public: + virtual ~AppControlTest() { + if (builder_ != nullptr) + app_control_uri_builder_destroy(builder_); + if (uri_ != nullptr) + app_control_uri_destroy(uri_); + } + + virtual void SetUp() { + app_control_uri_builder_create(&builder_); + EXPECT_NE(builder_, nullptr); + + app_control_uri_builder_set_scheme(builder_, "https"); + app_control_uri_builder_set_authority(builder_, + "//john.doe@www.example.com:123"); + app_control_uri_builder_set_path(builder_, "/forum/questions/"); + app_control_uri_builder_set_fragment(builder_, "top"); + app_control_uri_builder_add_query(builder_, "tag", "networking"); + app_control_uri_builder_add_query(builder_, "order", "newest"); + + app_control_uri_builder_build(builder_, &uri_); + EXPECT_NE(uri_, nullptr); + } + + virtual void TearDown() { + count_ = 0; + + if (builder_ != nullptr) { + auto builder = + std::unique_ptr( + builder_, app_control_uri_builder_destroy); + builder_ = nullptr; + } + if (uri_ != nullptr) { + auto uri = std::unique_ptr(uri_, + app_control_uri_destroy); + uri_ = nullptr; + } + } + + app_control_uri_builder_h builder_; + app_control_uri_h uri_; + int count_ = 0; +}; + +/* + * @testcase app_control_create_from_uri_handle_p + * @description Creates a app_control handle from uri handle. + * @apicovered app_control_create_from_uri_handle + */ +TEST_F(AppControlTest, app_control_create_from_uri_handle_p) { + app_control_h app_control; + int r = app_control_create_from_uri_handle(&app_control, uri_); + EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); + + std::unique_ptr::type, + decltype(app_control_destroy)*> handle(app_control, app_control_destroy); + + char *v; + r = app_control_get_uri(handle.get(), &v); + EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); + auto value = std::unique_ptr(v, std::free); + EXPECT_EQ(std::string(value.get()), EXAM_URI1); + + r = app_control_get_extra_data(handle.get(), "tag", &v); + EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); + value = std::unique_ptr(v, std::free); + EXPECT_EQ(std::string(value.get()), "networking"); +} + +/* + * @testcase app_control_set_uri_by_handle_p + * @description Sets uri data by uri handle. + * @apicovered app_control_set_uri_by_handle + */ +TEST_F(AppControlTest, app_control_set_uri_by_handle_p) { + app_control_h app_control; + int r = app_control_create(&app_control); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + std::unique_ptr::type, + decltype(app_control_destroy)*> handle(app_control, app_control_destroy); + + r = app_control_set_uri_by_handle(handle.get(), uri_); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + char *v; + r = app_control_get_uri(handle.get(), &v); + EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); + auto value = std::unique_ptr(v, std::free); + EXPECT_EQ(std::string(value.get()), EXAM_URI1); +} diff --git a/test/unit_tests/main.cc b/test/unit_tests/main.cc new file mode 100644 index 0000000..52fce8d --- /dev/null +++ b/test/unit_tests/main.cc @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019 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. + */ + +#include + +int gargc; +char** gargv; + +int main(int argc, char** argv) { + gargc = argc; + gargv = argv; + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/unit_tests/uri_unittest.cc b/test/unit_tests/uri_unittest.cc new file mode 100644 index 0000000..7a9b475 --- /dev/null +++ b/test/unit_tests/uri_unittest.cc @@ -0,0 +1,920 @@ +/* + * Copyright (c) 2019 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. + */ + +#include +#include + +#include +#include + +#include "include/app_control_uri.h" +#include "src/uri/uri_internal.h" + +// The source of the following example is "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier" +static const char EXAM_URI1[] = "https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top"; +static const char EXAM_URI2[] = "ldap://[2001:db8::7]/c=GB?objectClass?one"; +static const char EXAM_URI3[] = "mailto:John.Doe@example.com"; +static const char EXAM_URI4[] = "news:comp.infosystems.www.servers.unix"; +static const char EXAM_URI5[] = "tel:+1-816-555-1212"; +static const char EXAM_URI6[] = "telnet://192.0.2.16:80/"; +static const char EXAM_URI7[] = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; + +static const char ENCODED_URI1[] = "https:%2F%2Fjohn.doe%40www.example.com%3A123%2Fforum%2Fquestions%2F?tag=networking&order=newest#top"; +static const char ENCODED_URI2[] = "ldap:%2F%2F%5B2001%3Adb8%3A%3A7%5D%2Fc%3DGB?objectClass?one"; +static const char ENCODED_URI3[] = "mailto:John.Doe%40example.com"; +static const char ENCODED_URI4[] = "news:comp.infosystems.www.servers.unix"; +static const char ENCODED_URI5[] = "tel:%2B1-816-555-1212"; +static const char ENCODED_URI6[] = "telnet:%2F%2F192.0.2.16%3A80%2F"; +static const char ENCODED_URI7[] = "urn:oasis%3Anames%3Aspecification%3Adocbook%3Adtd%3Axml%3A4.1.2"; + +extern int gargc; +extern char** gargv; + +class UriTest : public testing::Test { + public: + virtual ~UriTest() { + if (builder_ != nullptr) + app_control_uri_builder_destroy(builder_); + if (uri_ != nullptr) + app_control_uri_destroy(uri_); + } + + virtual void SetUp() { + std::string exam_uri[] = { + ENCODED_URI1, + ENCODED_URI2, + ENCODED_URI3, + ENCODED_URI4, + ENCODED_URI5, + ENCODED_URI6, + ENCODED_URI7, + }; + + for (int i = 0; i < 7; i++) { + uri_list_[i] = + std::unique_ptr(new appcontrol::Uri(exam_uri[i])); + } + + app_control_uri_builder_create(&builder_); + EXPECT_NE(builder_, nullptr); + + app_control_uri_builder_set_scheme(builder_, "https"); + app_control_uri_builder_set_authority(builder_, + "//john.doe@www.example.com:123"); + app_control_uri_builder_set_path(builder_, "/forum/questions/"); + app_control_uri_builder_set_fragment(builder_, "top"); + app_control_uri_builder_add_query(builder_, "tag", "networking"); + app_control_uri_builder_add_query(builder_, "order", "newest"); + + app_control_uri_builder_build(builder_, &uri_); + EXPECT_NE(uri_, nullptr); + } + + virtual void TearDown() { + count_ = 0; + + if (builder_ != nullptr) { + auto builder = + std::unique_ptr( + builder_, app_control_uri_builder_destroy); + builder_ = nullptr; + } + if (uri_ != nullptr) { + auto uri = std::unique_ptr(uri_, + app_control_uri_destroy); + uri_ = nullptr; + } + } + + std::unique_ptr uri_list_[7]; + app_control_uri_builder_h builder_; + app_control_uri_h uri_; + int count_ = 0; +}; + +/* + * @testcase Uri_Constructor + * @description Creates a Uri object. + * @apicovered appcontrol::Uri + */ +TEST_F(UriTest, Uri_Constructor) { + std::unique_ptr uri = std::unique_ptr( + new appcontrol::Uri(ENCODED_URI1)); + EXPECT_NE(uri, nullptr); +} + +/* + * @testcase Uri_GetScheme + * @description Gets a scheme component from a URI object. + * @apicovered appcontrol::Uri::GetScheme + */ +TEST_F(UriTest, Uri_GetScheme) { + std::string exam_scheme[] = { + "https", + "ldap", + "mailto", + "news", + "tel", + "telnet", + "urn", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetScheme(), exam_scheme[i]); + } +} + +/* + * @testcase Uri_GetAuthority + * @description Gets an authority component from a URI object. + * @apicovered appcontrol::Uri::GetAuthority + */ +TEST_F(UriTest, Uri_GetAuthority) { + std::string exam_auth[] = { + "//john.doe@www.example.com:123", + "//[2001:db8::7]", + "", + "", + "", + "//192.0.2.16:80", + "", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetAuthority(), exam_auth[i]); + } +} + +/* + * @testcase Uri_GetPath + * @description Gets a path component from a URI object. + * @apicovered appcontrol::Uri::GetPath + */ +TEST_F(UriTest, Uri_GetPath) { + std::string exam_path[] = { + "/forum/questions/", + "/c=GB", + "John.Doe@example.com", + "comp.infosystems.www.servers.unix", + "+1-816-555-1212", + "/", + "oasis:names:specification:docbook:dtd:xml:4.1.2", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetPath(), exam_path[i]); + } +} + +/* + * @testcase Uri_GetFragment + * @description Gets a fragment component from a URI object. + * @apicovered appcontrol::Uri::GetFragment + */ +TEST_F(UriTest, Uri_GetFragment) { + std::string exam_fragment[] = { + "top", + "", + "", + "", + "", + "", + "", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetFragment(), exam_fragment[i]); + } +} + +/* + * @testcase Uri_GetHost + * @description Gets a host subcomponent from a URI object. + * @apicovered appcontrol::Uri::GetHost + */ +TEST_F(UriTest, Uri_GetHost) { + std::string exam_host[] = { + "www.example.com", + "[2001:db8::7]", + "", + "", + "", + "192.0.2.16", + "", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetHost(), exam_host[i]); + } +} + +/* + * @testcase Uri_GetPort + * @description Gets a port subcomponent from a URI object. + * @apicovered appcontrol::Uri::GetPort + */ +TEST_F(UriTest, Uri_GetPort) { + std::string exam_port[] = { + "123", + "", + "", + "", + "", + "80", + "", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetPort(), exam_port[i]); + } +} + +/* + * @testcase Uri_GetUser + * @description Gets a user subcomponent from a URI object. + * @apicovered appcontrol::Uri::GetUser + */ +TEST_F(UriTest, Uri_GetUser) { + std::string exam_user[] = { + "john.doe", + "", + "", + "", + "", + "", + "", + }; + + for (int i = 0; i < 7; i++) { + EXPECT_EQ(uri_list_[i]->GetUser(), exam_user[i]); + } +} + +/* + * @testcase Uri_GetQuery + * @description Gets a query component from a URI object. + * @apicovered appcontrol::Uri::GetQuery + */ +TEST_F(UriTest, Uri_GetQuery) { + int match_count = 0; + auto& query = uri_list_[0]->GetQuery(); + for (auto& i : query) { + if (i.first == "tag" && + i.second == "networking") { + match_count++; + } else if (i.first == "order" && + i.second == "newest") { + match_count++; + } + } + + EXPECT_EQ(match_count, 2); +} + +/* + * @testcase Uri_Encode + * @description Encodes a URI object to string. + * @apicovered appcontrol::Uri::Encode + */ +TEST_F(UriTest, Uri_Encode) { + std::unique_ptr uri = std::unique_ptr( + new appcontrol::Uri(EXAM_URI1)); + EXPECT_NE(uri, nullptr); + EXPECT_EQ(uri->Encode(), ENCODED_URI1); +} + +/* + * @testcase Uri_Builder + * @description Builds a URI builder object to create a URI object. + * @apicovered appcontrol::Uri::Builder, appcontrol::Uri::Builder::SetScheme, + * appcontrol::Uri::Builder::SetAuthority, appcontrol::Uri::Builder::SetPath, + * appcontrol::Uri::Builder::AddQuery, appcontrol::Uri::Builder::SetFragment, + * appcontrol::Uri::Builder::Build + */ +TEST_F(UriTest, Uri_Builder) { + std::unique_ptr builder(new appcontrol::Uri::Builder()); + EXPECT_NE(builder, nullptr); + builder->SetScheme("https"); + builder->SetAuthority("//john.doe@www.example.com:123"); + builder->SetPath("/forum/questions/"); + builder->AddQuery("tag", "networking"); + builder->AddQuery("order", "newest"); + builder->SetFragment("top"); + + appcontrol::Uri uri = builder->Build(); + EXPECT_EQ(uri.Encode(), ENCODED_URI1); +} + +/* + * @testcase app_control_uri_builder_create_p + * @description Creates a URI builder handle. + * @apicovered app_control_uri_builder_create + */ +TEST_F(UriTest, app_control_uri_builder_create_p) { + app_control_uri_builder_h builder = nullptr; + int r = app_control_uri_builder_create(&builder); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(builder, nullptr); + app_control_uri_builder_destroy(builder); +} + +/* + * @testcase app_control_uri_builder_create_n + * @description Creates a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_create + */ +TEST_F(UriTest, app_control_uri_builder_create_n) { + int r = app_control_uri_builder_create(nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_set_scheme_p + * @description Sets a scheme component to a URI builder handle. + * @apicovered app_control_uri_builder_set_scheme + */ +TEST_F(UriTest, app_control_uri_builder_set_scheme_p) { + int r = app_control_uri_builder_set_scheme(builder_, "https"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_set_scheme_n + * @description Sets a scheme component to a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_set_scheme + */ +TEST_F(UriTest, app_control_uri_builder_set_scheme_n) { + int r = app_control_uri_builder_set_scheme(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_set_scheme(nullptr, "https"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_set_authority_p + * @description Sets an authority component to a URI builder handle. + * @apicovered app_control_uri_builder_set_authority + */ +TEST_F(UriTest, app_control_uri_builder_set_authority_p) { + int r = app_control_uri_builder_set_authority(builder_, + "//john.doe@www.example.com:123"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_set_authority_n + * @description Sets an authority component to a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_set_authority + */ +TEST_F(UriTest, app_control_uri_builder_set_authority_n) { + int r = app_control_uri_builder_set_authority(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_set_authority(nullptr, + "//john.doe@www.example.com:123"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_set_path_p + * @description Sets a path component to a URI builder handle. + * @apicovered app_control_uri_builder_set_path + */ +TEST_F(UriTest, app_control_uri_builder_set_path_p) { + int r = app_control_uri_builder_set_path(builder_, "/forum/questions/"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_set_path_n + * @description Sets a path component to a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_set_path + */ +TEST_F(UriTest, app_control_uri_builder_set_path_n) { + int r = app_control_uri_builder_set_path(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_set_path(nullptr, "/forum/questions/"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_add_path_p + * @description Adds a path component on a URI builder handle. + * @apicovered app_control_uri_builder_add_path + */ +TEST_F(UriTest, app_control_uri_builder_add_path_p) { + int r = app_control_uri_builder_add_path(builder_, "/forum"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + r = app_control_uri_builder_add_path(builder_, "/questions/"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_add_path_n + * @description Adds a path component on a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_add_path + */ +TEST_F(UriTest, app_control_uri_builder_add_path_n) { + int r = app_control_uri_builder_add_path(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_add_path(nullptr, "/questions/"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_set_fragment_p + * @description Sets a fragment component to a URI builder handle. + * @apicovered app_control_uri_builder_set_fragment + */ +TEST_F(UriTest, app_control_uri_builder_set_fragment_p) { + int r = app_control_uri_builder_set_fragment(builder_, "top"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_set_fragment_n + * @description Sets a fragment component to a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_set_fragment + */ +TEST_F(UriTest, app_control_uri_builder_set_fragment_n) { + int r = app_control_uri_builder_set_fragment(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_set_fragment(nullptr, "top"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_add_query_p + * @description Adds a query component on a URI builder handle. + * @apicovered app_control_uri_builder_add_query + */ +TEST_F(UriTest, app_control_uri_builder_add_query_p) { + int r = app_control_uri_builder_add_query(builder_, "tag", "networking"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + r = app_control_uri_builder_add_query(builder_, "order", "newest"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); +} + +/* + * @testcase app_control_uri_builder_add_query_n + * @description Adds a query component on a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_add_query + */ +TEST_F(UriTest, app_control_uri_builder_add_query_n) { + int r = app_control_uri_builder_add_query(builder_, "tag", nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_add_query(builder_, nullptr, "newest"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_builder_add_query(nullptr, "tag", "newest"); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_build_p + * @description Builds a URI builder handle to create a URI handle. + * @apicovered app_control_uri_builder_build + */ +TEST_F(UriTest, app_control_uri_builder_build_p) { + app_control_uri_h app_control_uri = nullptr; + int r = app_control_uri_builder_build(builder_, &app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(app_control_uri, nullptr); + app_control_uri_destroy(app_control_uri); +} + +/* + * @testcase app_control_uri_builder_build_n + * @description Builds a URI builder handle to create a URI handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_build + */ +TEST_F(UriTest, app_control_uri_builder_build_n) { + int r = app_control_uri_builder_build(builder_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + app_control_uri_h app_control_uri = nullptr; + r = app_control_uri_builder_build(nullptr, &app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_builder_destroy_p + * @description Destroys a URI builder handle. + * @apicovered app_control_uri_builder_destroy + */ +TEST_F(UriTest, app_control_uri_builder_destroy_p) { + int r = app_control_uri_builder_destroy(builder_); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + builder_ = nullptr; +} + +/* + * @testcase app_control_uri_builder_destroy_n + * @description Destroys a URI builder handle. + * The function returns a negative error value. + * @apicovered app_control_uri_builder_destroy + */ +TEST_F(UriTest, app_control_uri_builder_destroy_n) { + int r = app_control_uri_builder_destroy(nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_create_p + * @description Creates a URI builder handle from an encoded URI string. + * @apicovered app_control_uri_create + */ +TEST_F(UriTest, app_control_uri_create_p) { + app_control_uri_h app_control_uri = nullptr; + const char *scheme; + const char *authority; + const char *path; + const char *fragment; + const char *host; + const char *port; + const char *user; + int r = app_control_uri_create(ENCODED_URI1, &app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + auto handle = std::unique_ptr( + app_control_uri, app_control_uri_destroy); + + r = app_control_uri_get_scheme(handle.get(), &scheme); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + r = app_control_uri_get_authority(handle.get(), &authority); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + r = app_control_uri_get_path(handle.get(), &path); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + r = app_control_uri_get_fragment(handle.get(), &fragment); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + EXPECT_EQ(std::string(scheme), "https"); + EXPECT_EQ(std::string(authority), "//john.doe@www.example.com:123"); + EXPECT_EQ(std::string(path), "/forum/questions/"); + EXPECT_EQ(std::string(fragment), "top"); + + app_control_uri_query_h query = nullptr; + r = app_control_uri_get_query(handle.get(), &query); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(query, nullptr); + + r = app_control_uri_get_host(handle.get(), &host); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + r = app_control_uri_get_port(handle.get(), &port); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + r = app_control_uri_get_user(handle.get(), &user); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + + EXPECT_EQ(std::string(host), "www.example.com"); + EXPECT_EQ(std::string(port), "123"); + EXPECT_EQ(std::string(user), "john.doe"); +} + +/* + * @testcase app_control_uri_create_n + * @description Creates a URI builder handle from an encoded URI string. + * The function returns a negative error value. + * @apicovered app_control_uri_create + */ +TEST_F(UriTest, app_control_uri_create_n) { + int r = app_control_uri_create(ENCODED_URI1, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + app_control_uri_h app_control_uri = nullptr; + r = app_control_uri_create(nullptr, &app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_destroy_p + * @description Destroys a URI handle. + * @apicovered app_control_uri_destroy + */ +TEST_F(UriTest, app_control_uri_destroy_p) { + int r = app_control_uri_destroy(uri_); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + uri_ = nullptr; +} + +/* + * @testcase app_control_uri_destroy_n + * @description Destroys a URI handle. + * The function returns a negative error value. + * @apicovered app_control_uri_destroy + */ +TEST_F(UriTest, app_control_uri_destroy_n) { + int r = app_control_uri_destroy(nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_encode_p + * @description Encodes a URI handle to string. + * @apicovered app_control_uri_encode + */ +TEST_F(UriTest, app_control_uri_encode_p) { + char *encoded_app_control_uri = nullptr; + int r = app_control_uri_encode(uri_, &encoded_app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_EQ(std::string(encoded_app_control_uri), ENCODED_URI1); + if (encoded_app_control_uri) + free(encoded_app_control_uri); +} + +/* + * @testcase app_control_uri_encode_n + * @description Encodes a URI handle to string. + * The function returns a nullptr. + * @apicovered app_control_uri_encode + */ +TEST_F(UriTest, app_control_uri_encode_n) { + char *encoded_app_control_uri; + int r = app_control_uri_encode(nullptr, &encoded_app_control_uri); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_scheme_p + * @description Gets a scheme component from a URI handle. + * @apicovered app_control_uri_get_scheme + */ +TEST_F(UriTest, app_control_uri_get_scheme_p) { + const char* scheme; + int r = app_control_uri_get_scheme(uri_, &scheme); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(scheme, nullptr); + EXPECT_EQ(std::string(scheme), "https"); +} + +/* + * @testcase app_control_uri_get_scheme_n + * @description Gets a scheme component from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_scheme + */ +TEST_F(UriTest, app_control_uri_get_scheme_n) { + const char* scheme; + int r = app_control_uri_get_scheme(nullptr, &scheme); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_authority_p + * @description Gets an authority component from a URI handle. + * @apicovered app_control_uri_get_authority + */ +TEST_F(UriTest, app_control_uri_get_authority_p) { + const char* auth; + int r = app_control_uri_get_authority(uri_, &auth); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(auth, nullptr); + EXPECT_EQ(std::string(auth), "//john.doe@www.example.com:123"); +} + +/* + * @testcase app_control_uri_get_authority_n + * @description Gets an authority component from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_authority + */ +TEST_F(UriTest, app_control_uri_get_authority_n) { + const char* auth; + int r = app_control_uri_get_authority(nullptr, &auth); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_path_p + * @description Gets a path component from a URI handle. + * @apicovered app_control_uri_get_path + */ +TEST_F(UriTest, app_control_uri_get_path_p) { + const char* path; + int r = app_control_uri_get_path(uri_, &path); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(path, nullptr); + EXPECT_EQ(std::string(path), "/forum/questions/"); +} + +/* + * @testcase app_control_uri_get_path_n + * @description Gets a path component from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_path + */ +TEST_F(UriTest, app_control_uri_get_path_n) { + const char* path; + int r = app_control_uri_get_path(nullptr, &path); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_fragment_p + * @description Gets a fragment component from a URI handle. + * @apicovered app_control_uri_get_fragment + */ +TEST_F(UriTest, app_control_uri_get_fragment_p) { + const char* fragment; + int r = app_control_uri_get_fragment(uri_, &fragment); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(fragment, nullptr); + EXPECT_EQ(std::string(fragment), "top"); +} + +/* + * @testcase app_control_uri_get_fragment_n + * @description Gets a fragment component from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_fragment + */ +TEST_F(UriTest, app_control_uri_get_fragment_n) { + const char* fragment; + int r = app_control_uri_get_fragment(nullptr, &fragment); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_query_p + * @description Gets a handle of the query component from a URI handle. + * @apicovered app_control_uri_get_query + */ +TEST_F(UriTest, app_control_uri_get_query_p) { + app_control_uri_query_h query = nullptr; + int r = app_control_uri_get_query(uri_, &query); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(query, nullptr); +} + +/* + * @testcase app_control_uri_get_query_n + * @description Gets a handle of the query component from a URI handle. + * The function returns a negative error value. + * @apicovered app_control_uri_get_query + */ +TEST_F(UriTest, app_control_uri_get_query_n) { + int r = app_control_uri_get_query(uri_, nullptr); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + app_control_uri_query_h query = nullptr; + r = app_control_uri_get_query(nullptr, &query); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_host_p + * @description Gets a host subcomponent from a URI handle. + * @apicovered app_control_uri_get_host + */ +TEST_F(UriTest, app_control_uri_get_host_p) { + const char* host; + int r = app_control_uri_get_host(uri_, &host); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(host, nullptr); + EXPECT_EQ(std::string(host), "www.example.com"); +} + +/* + * @testcase app_control_uri_get_host_n + * @description Gets a host subcomponent from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_host + */ +TEST_F(UriTest, app_control_uri_get_host_n) { + const char* host; + int r = app_control_uri_get_host(nullptr, &host); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_port_p + * @description Gets a port subcomponent from a URI handle. + * @apicovered app_control_uri_get_port + */ +TEST_F(UriTest, app_control_uri_get_port_p) { + const char* port; + int r = app_control_uri_get_port(uri_, &port); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(port, nullptr); + EXPECT_EQ(std::string(port), "123"); +} + +/* + * @testcase app_control_uri_get_port_n + * @description Gets a port subcomponent from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_port + */ +TEST_F(UriTest, app_control_uri_get_port_n) { + const char* port; + int r = app_control_uri_get_port(nullptr, &port); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_get_user_p + * @description Gets a user subcomponent from a URI handle. + * @apicovered app_control_uri_get_user + */ +TEST_F(UriTest, app_control_uri_get_user_p) { + const char* user; + int r = app_control_uri_get_user(uri_, &user); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(user, nullptr); + EXPECT_EQ(std::string(user), "john.doe"); +} + +/* + * @testcase app_control_uri_get_user_n + * @description Gets a user subcomponent from a URI handle. + * The function returns a nullptr. + * @apicovered app_control_uri_get_user + */ +TEST_F(UriTest, app_control_uri_get_user_n) { + const char* user; + int r = app_control_uri_get_user(nullptr, &user); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); +} + +/* + * @testcase app_control_uri_query_foreach_p + * @description Retrieves the key-value pairs attributes in the query component. + * @apicovered app_control_uri_query_foreach + */ +TEST_F(UriTest, app_control_uri_query_foreach_p) { + // Pre-condition: Gets the query handle + app_control_uri_query_h query = nullptr; + int r = app_control_uri_get_query(uri_, &query); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(query, nullptr); + + r = app_control_uri_query_foreach(query, + [](const char* key, const char* val, void* user_data) -> bool { + UriTest* p = static_cast(user_data); + if (!strcmp(key, "tag") && !strcmp(val, "networking")) + p->count_++; + else if (!strcmp(key, "order") && !strcmp(val, "newest")) + p->count_++; + return true; + }, this); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_EQ(count_, 2); +} + +/* + * @testcase app_control_uri_query_foreach_n + * @description Retrieves the key-value pairs attributes in the query component. + * The function returns a negative error value. + * @apicovered app_control_uri_query_foreach + */ +TEST_F(UriTest, app_control_uri_query_foreach_n) { + // Pre-condition: Gets the query handle + app_control_uri_query_h query = nullptr; + int r = app_control_uri_get_query(uri_, &query); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); + EXPECT_NE(query, nullptr); + + r = app_control_uri_query_foreach(query, nullptr, this); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + + r = app_control_uri_query_foreach(nullptr, + [](const char* key, const char* val, void* user_data) -> bool { + UriTest* p = static_cast(user_data); + if (!strcmp(key, "tag") && !strcmp(val, "networking")) + p->count_++; + else if (!strcmp(key, "order") && !strcmp(val, "newest")) + p->count_++; + return true; + }, this); + EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); + EXPECT_EQ(count_, 0); +} diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt deleted file mode 100644 index f3daf08..0000000 --- a/unit_tests/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(appctrl_unittests CXX) - -INCLUDE(FindPkgConfig) -pkg_check_modules(appctrl_unittests REQUIRED - glib-2.0 - gmock - aul - appcore-common -) - -FOREACH(flag ${appctrl_unittests_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline") -SET(CMAKE_C_FLAGS "${EXTRA_CFLAGS} ${EXTRA_CFLAGS}") - -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11") -SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") -SET(CMAKE_CXX_FLAGS_RELEASE "-O2") -SET(SOURCES - ${CMAKE_SOURCE_DIR}/src/app_control.c - ${CMAKE_SOURCE_DIR}/src/uri/uri_internal.cc - ${CMAKE_SOURCE_DIR}/src/uri/app_control_uri.cc) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR}/../src/uri - ) - -AUX_SOURCE_DIRECTORY(src TEST_SOURCES) -ADD_EXECUTABLE(${PROJECT_NAME} - ${SOURCES} - ${TEST_SOURCES} -) - -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}") -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${appctrl_unittests_LDFLAGS}) - -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin) diff --git a/unit_tests/src/app_control_unittest.cc b/unit_tests/src/app_control_unittest.cc deleted file mode 100644 index 8cef8bc..0000000 --- a/unit_tests/src/app_control_unittest.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#include -#include -#include -#include - -#include -#include - -#include "uri_internal.h" - -// The source of the following example is "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier" -static const char EXAM_URI1[] = "https://john.doe@www.example.com:123"; -extern int gargc; -extern char** gargv; - -class AppControlTest : public testing::Test { - public: - virtual ~AppControlTest() { - if (builder_ != nullptr) - app_control_uri_builder_destroy(builder_); - if (uri_ != nullptr) - app_control_uri_destroy(uri_); - } - - virtual void SetUp() { - app_control_uri_builder_create(&builder_); - EXPECT_NE(builder_, nullptr); - - app_control_uri_builder_set_scheme(builder_, "https"); - app_control_uri_builder_set_authority(builder_, - "//john.doe@www.example.com:123"); - app_control_uri_builder_set_path(builder_, "/forum/questions/"); - app_control_uri_builder_set_fragment(builder_, "top"); - app_control_uri_builder_add_query(builder_, "tag", "networking"); - app_control_uri_builder_add_query(builder_, "order", "newest"); - - app_control_uri_builder_build(builder_, &uri_); - EXPECT_NE(uri_, nullptr); - } - - virtual void TearDown() { - count_ = 0; - - if (builder_ != nullptr) { - auto builder = - std::unique_ptr( - builder_, app_control_uri_builder_destroy); - builder_ = nullptr; - } - if (uri_ != nullptr) { - auto uri = std::unique_ptr(uri_, - app_control_uri_destroy); - uri_ = nullptr; - } - } - - app_control_uri_builder_h builder_; - app_control_uri_h uri_; - int count_ = 0; -}; - -/* - * @testcase app_control_create_from_uri_handle_p - * @description Creates a app_control handle from uri handle. - * @apicovered app_control_create_from_uri_handle - */ -TEST_F(AppControlTest, app_control_create_from_uri_handle_p) { - app_control_h app_control; - int r = app_control_create_from_uri_handle(&app_control, uri_); - EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); - - std::unique_ptr::type, - decltype(app_control_destroy)*> handle(app_control, app_control_destroy); - - char *v; - r = app_control_get_uri(handle.get(), &v); - EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); - auto value = std::unique_ptr(v, std::free); - EXPECT_EQ(std::string(value.get()), EXAM_URI1); - - r = app_control_get_extra_data(handle.get(), "tag", &v); - EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); - value = std::unique_ptr(v, std::free); - EXPECT_EQ(std::string(value.get()), "networking"); -} - -/* - * @testcase app_control_set_uri_by_handle_p - * @description Sets uri data by uri handle. - * @apicovered app_control_set_uri_by_handle - */ -TEST_F(AppControlTest, app_control_set_uri_by_handle_p) { - app_control_h app_control; - int r = app_control_create(&app_control); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - std::unique_ptr::type, - decltype(app_control_destroy)*> handle(app_control, app_control_destroy); - - r = app_control_set_uri_by_handle(handle.get(), uri_); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - char *v; - r = app_control_get_uri(handle.get(), &v); - EXPECT_EQ(r, APP_CONTROL_ERROR_NONE); - auto value = std::unique_ptr(v, std::free); - EXPECT_EQ(std::string(value.get()), EXAM_URI1); -} diff --git a/unit_tests/src/main.cc b/unit_tests/src/main.cc deleted file mode 100644 index 52fce8d..0000000 --- a/unit_tests/src/main.cc +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#include - -int gargc; -char** gargv; - -int main(int argc, char** argv) { - gargc = argc; - gargv = argv; - - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/unit_tests/src/uri_unittest.cc b/unit_tests/src/uri_unittest.cc deleted file mode 100644 index f1272dd..0000000 --- a/unit_tests/src/uri_unittest.cc +++ /dev/null @@ -1,920 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#include -#include -#include - -#include -#include - -#include "uri_internal.h" - -// The source of the following example is "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier" -static const char EXAM_URI1[] = "https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top"; -static const char EXAM_URI2[] = "ldap://[2001:db8::7]/c=GB?objectClass?one"; -static const char EXAM_URI3[] = "mailto:John.Doe@example.com"; -static const char EXAM_URI4[] = "news:comp.infosystems.www.servers.unix"; -static const char EXAM_URI5[] = "tel:+1-816-555-1212"; -static const char EXAM_URI6[] = "telnet://192.0.2.16:80/"; -static const char EXAM_URI7[] = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; - -static const char ENCODED_URI1[] = "https:%2F%2Fjohn.doe%40www.example.com%3A123%2Fforum%2Fquestions%2F?tag=networking&order=newest#top"; -static const char ENCODED_URI2[] = "ldap:%2F%2F%5B2001%3Adb8%3A%3A7%5D%2Fc%3DGB?objectClass?one"; -static const char ENCODED_URI3[] = "mailto:John.Doe%40example.com"; -static const char ENCODED_URI4[] = "news:comp.infosystems.www.servers.unix"; -static const char ENCODED_URI5[] = "tel:%2B1-816-555-1212"; -static const char ENCODED_URI6[] = "telnet:%2F%2F192.0.2.16%3A80%2F"; -static const char ENCODED_URI7[] = "urn:oasis%3Anames%3Aspecification%3Adocbook%3Adtd%3Axml%3A4.1.2"; - -extern int gargc; -extern char** gargv; - -class UriTest : public testing::Test { - public: - virtual ~UriTest() { - if (builder_ != nullptr) - app_control_uri_builder_destroy(builder_); - if (uri_ != nullptr) - app_control_uri_destroy(uri_); - } - - virtual void SetUp() { - std::string exam_uri[] = { - ENCODED_URI1, - ENCODED_URI2, - ENCODED_URI3, - ENCODED_URI4, - ENCODED_URI5, - ENCODED_URI6, - ENCODED_URI7, - }; - - for (int i = 0; i < 7; i++) { - uri_list_[i] = - std::unique_ptr(new appcontrol::Uri(exam_uri[i])); - } - - app_control_uri_builder_create(&builder_); - EXPECT_NE(builder_, nullptr); - - app_control_uri_builder_set_scheme(builder_, "https"); - app_control_uri_builder_set_authority(builder_, - "//john.doe@www.example.com:123"); - app_control_uri_builder_set_path(builder_, "/forum/questions/"); - app_control_uri_builder_set_fragment(builder_, "top"); - app_control_uri_builder_add_query(builder_, "tag", "networking"); - app_control_uri_builder_add_query(builder_, "order", "newest"); - - app_control_uri_builder_build(builder_, &uri_); - EXPECT_NE(uri_, nullptr); - } - - virtual void TearDown() { - count_ = 0; - - if (builder_ != nullptr) { - auto builder = - std::unique_ptr( - builder_, app_control_uri_builder_destroy); - builder_ = nullptr; - } - if (uri_ != nullptr) { - auto uri = std::unique_ptr(uri_, - app_control_uri_destroy); - uri_ = nullptr; - } - } - - std::unique_ptr uri_list_[7]; - app_control_uri_builder_h builder_; - app_control_uri_h uri_; - int count_ = 0; -}; - -/* - * @testcase Uri_Constructor - * @description Creates a Uri object. - * @apicovered appcontrol::Uri - */ -TEST_F(UriTest, Uri_Constructor) { - std::unique_ptr uri = std::unique_ptr( - new appcontrol::Uri(ENCODED_URI1)); - EXPECT_NE(uri, nullptr); -} - -/* - * @testcase Uri_GetScheme - * @description Gets a scheme component from a URI object. - * @apicovered appcontrol::Uri::GetScheme - */ -TEST_F(UriTest, Uri_GetScheme) { - std::string exam_scheme[] = { - "https", - "ldap", - "mailto", - "news", - "tel", - "telnet", - "urn", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetScheme(), exam_scheme[i]); - } -} - -/* - * @testcase Uri_GetAuthority - * @description Gets an authority component from a URI object. - * @apicovered appcontrol::Uri::GetAuthority - */ -TEST_F(UriTest, Uri_GetAuthority) { - std::string exam_auth[] = { - "//john.doe@www.example.com:123", - "//[2001:db8::7]", - "", - "", - "", - "//192.0.2.16:80", - "", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetAuthority(), exam_auth[i]); - } -} - -/* - * @testcase Uri_GetPath - * @description Gets a path component from a URI object. - * @apicovered appcontrol::Uri::GetPath - */ -TEST_F(UriTest, Uri_GetPath) { - std::string exam_path[] = { - "/forum/questions/", - "/c=GB", - "John.Doe@example.com", - "comp.infosystems.www.servers.unix", - "+1-816-555-1212", - "/", - "oasis:names:specification:docbook:dtd:xml:4.1.2", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetPath(), exam_path[i]); - } -} - -/* - * @testcase Uri_GetFragment - * @description Gets a fragment component from a URI object. - * @apicovered appcontrol::Uri::GetFragment - */ -TEST_F(UriTest, Uri_GetFragment) { - std::string exam_fragment[] = { - "top", - "", - "", - "", - "", - "", - "", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetFragment(), exam_fragment[i]); - } -} - -/* - * @testcase Uri_GetHost - * @description Gets a host subcomponent from a URI object. - * @apicovered appcontrol::Uri::GetHost - */ -TEST_F(UriTest, Uri_GetHost) { - std::string exam_host[] = { - "www.example.com", - "[2001:db8::7]", - "", - "", - "", - "192.0.2.16", - "", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetHost(), exam_host[i]); - } -} - -/* - * @testcase Uri_GetPort - * @description Gets a port subcomponent from a URI object. - * @apicovered appcontrol::Uri::GetPort - */ -TEST_F(UriTest, Uri_GetPort) { - std::string exam_port[] = { - "123", - "", - "", - "", - "", - "80", - "", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetPort(), exam_port[i]); - } -} - -/* - * @testcase Uri_GetUser - * @description Gets a user subcomponent from a URI object. - * @apicovered appcontrol::Uri::GetUser - */ -TEST_F(UriTest, Uri_GetUser) { - std::string exam_user[] = { - "john.doe", - "", - "", - "", - "", - "", - "", - }; - - for (int i = 0; i < 7; i++) { - EXPECT_EQ(uri_list_[i]->GetUser(), exam_user[i]); - } -} - -/* - * @testcase Uri_GetQuery - * @description Gets a query component from a URI object. - * @apicovered appcontrol::Uri::GetQuery - */ -TEST_F(UriTest, Uri_GetQuery) { - int match_count = 0; - auto& query = uri_list_[0]->GetQuery(); - for (auto& i : query) { - if (i.first == "tag" && - i.second == "networking") { - match_count++; - } else if (i.first == "order" && - i.second == "newest") { - match_count++; - } - } - - EXPECT_EQ(match_count, 2); -} - -/* - * @testcase Uri_Encode - * @description Encodes a URI object to string. - * @apicovered appcontrol::Uri::Encode - */ -TEST_F(UriTest, Uri_Encode) { - std::unique_ptr uri = std::unique_ptr( - new appcontrol::Uri(EXAM_URI1)); - EXPECT_NE(uri, nullptr); - EXPECT_EQ(uri->Encode(), ENCODED_URI1); -} - -/* - * @testcase Uri_Builder - * @description Builds a URI builder object to create a URI object. - * @apicovered appcontrol::Uri::Builder, appcontrol::Uri::Builder::SetScheme, - * appcontrol::Uri::Builder::SetAuthority, appcontrol::Uri::Builder::SetPath, - * appcontrol::Uri::Builder::AddQuery, appcontrol::Uri::Builder::SetFragment, - * appcontrol::Uri::Builder::Build - */ -TEST_F(UriTest, Uri_Builder) { - std::unique_ptr builder(new appcontrol::Uri::Builder()); - EXPECT_NE(builder, nullptr); - builder->SetScheme("https"); - builder->SetAuthority("//john.doe@www.example.com:123"); - builder->SetPath("/forum/questions/"); - builder->AddQuery("tag", "networking"); - builder->AddQuery("order", "newest"); - builder->SetFragment("top"); - - appcontrol::Uri uri = builder->Build(); - EXPECT_EQ(uri.Encode(), ENCODED_URI1); -} - -/* - * @testcase app_control_uri_builder_create_p - * @description Creates a URI builder handle. - * @apicovered app_control_uri_builder_create - */ -TEST_F(UriTest, app_control_uri_builder_create_p) { - app_control_uri_builder_h builder = nullptr; - int r = app_control_uri_builder_create(&builder); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(builder, nullptr); - app_control_uri_builder_destroy(builder); -} - -/* - * @testcase app_control_uri_builder_create_n - * @description Creates a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_create - */ -TEST_F(UriTest, app_control_uri_builder_create_n) { - int r = app_control_uri_builder_create(nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_set_scheme_p - * @description Sets a scheme component to a URI builder handle. - * @apicovered app_control_uri_builder_set_scheme - */ -TEST_F(UriTest, app_control_uri_builder_set_scheme_p) { - int r = app_control_uri_builder_set_scheme(builder_, "https"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_set_scheme_n - * @description Sets a scheme component to a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_set_scheme - */ -TEST_F(UriTest, app_control_uri_builder_set_scheme_n) { - int r = app_control_uri_builder_set_scheme(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_set_scheme(nullptr, "https"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_set_authority_p - * @description Sets an authority component to a URI builder handle. - * @apicovered app_control_uri_builder_set_authority - */ -TEST_F(UriTest, app_control_uri_builder_set_authority_p) { - int r = app_control_uri_builder_set_authority(builder_, - "//john.doe@www.example.com:123"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_set_authority_n - * @description Sets an authority component to a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_set_authority - */ -TEST_F(UriTest, app_control_uri_builder_set_authority_n) { - int r = app_control_uri_builder_set_authority(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_set_authority(nullptr, - "//john.doe@www.example.com:123"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_set_path_p - * @description Sets a path component to a URI builder handle. - * @apicovered app_control_uri_builder_set_path - */ -TEST_F(UriTest, app_control_uri_builder_set_path_p) { - int r = app_control_uri_builder_set_path(builder_, "/forum/questions/"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_set_path_n - * @description Sets a path component to a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_set_path - */ -TEST_F(UriTest, app_control_uri_builder_set_path_n) { - int r = app_control_uri_builder_set_path(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_set_path(nullptr, "/forum/questions/"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_add_path_p - * @description Adds a path component on a URI builder handle. - * @apicovered app_control_uri_builder_add_path - */ -TEST_F(UriTest, app_control_uri_builder_add_path_p) { - int r = app_control_uri_builder_add_path(builder_, "/forum"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - r = app_control_uri_builder_add_path(builder_, "/questions/"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_add_path_n - * @description Adds a path component on a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_add_path - */ -TEST_F(UriTest, app_control_uri_builder_add_path_n) { - int r = app_control_uri_builder_add_path(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_add_path(nullptr, "/questions/"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_set_fragment_p - * @description Sets a fragment component to a URI builder handle. - * @apicovered app_control_uri_builder_set_fragment - */ -TEST_F(UriTest, app_control_uri_builder_set_fragment_p) { - int r = app_control_uri_builder_set_fragment(builder_, "top"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_set_fragment_n - * @description Sets a fragment component to a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_set_fragment - */ -TEST_F(UriTest, app_control_uri_builder_set_fragment_n) { - int r = app_control_uri_builder_set_fragment(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_set_fragment(nullptr, "top"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_add_query_p - * @description Adds a query component on a URI builder handle. - * @apicovered app_control_uri_builder_add_query - */ -TEST_F(UriTest, app_control_uri_builder_add_query_p) { - int r = app_control_uri_builder_add_query(builder_, "tag", "networking"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - r = app_control_uri_builder_add_query(builder_, "order", "newest"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); -} - -/* - * @testcase app_control_uri_builder_add_query_n - * @description Adds a query component on a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_add_query - */ -TEST_F(UriTest, app_control_uri_builder_add_query_n) { - int r = app_control_uri_builder_add_query(builder_, "tag", nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_add_query(builder_, nullptr, "newest"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_builder_add_query(nullptr, "tag", "newest"); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_build_p - * @description Builds a URI builder handle to create a URI handle. - * @apicovered app_control_uri_builder_build - */ -TEST_F(UriTest, app_control_uri_builder_build_p) { - app_control_uri_h app_control_uri = nullptr; - int r = app_control_uri_builder_build(builder_, &app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(app_control_uri, nullptr); - app_control_uri_destroy(app_control_uri); -} - -/* - * @testcase app_control_uri_builder_build_n - * @description Builds a URI builder handle to create a URI handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_build - */ -TEST_F(UriTest, app_control_uri_builder_build_n) { - int r = app_control_uri_builder_build(builder_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - app_control_uri_h app_control_uri = nullptr; - r = app_control_uri_builder_build(nullptr, &app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_builder_destroy_p - * @description Destroys a URI builder handle. - * @apicovered app_control_uri_builder_destroy - */ -TEST_F(UriTest, app_control_uri_builder_destroy_p) { - int r = app_control_uri_builder_destroy(builder_); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - builder_ = nullptr; -} - -/* - * @testcase app_control_uri_builder_destroy_n - * @description Destroys a URI builder handle. - * The function returns a negative error value. - * @apicovered app_control_uri_builder_destroy - */ -TEST_F(UriTest, app_control_uri_builder_destroy_n) { - int r = app_control_uri_builder_destroy(nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_create_p - * @description Creates a URI builder handle from an encoded URI string. - * @apicovered app_control_uri_create - */ -TEST_F(UriTest, app_control_uri_create_p) { - app_control_uri_h app_control_uri = nullptr; - const char *scheme; - const char *authority; - const char *path; - const char *fragment; - const char *host; - const char *port; - const char *user; - int r = app_control_uri_create(ENCODED_URI1, &app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - auto handle = std::unique_ptr( - app_control_uri, app_control_uri_destroy); - - r = app_control_uri_get_scheme(handle.get(), &scheme); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - r = app_control_uri_get_authority(handle.get(), &authority); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - r = app_control_uri_get_path(handle.get(), &path); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - r = app_control_uri_get_fragment(handle.get(), &fragment); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - EXPECT_EQ(std::string(scheme), "https"); - EXPECT_EQ(std::string(authority), "//john.doe@www.example.com:123"); - EXPECT_EQ(std::string(path), "/forum/questions/"); - EXPECT_EQ(std::string(fragment), "top"); - - app_control_uri_query_h query = nullptr; - r = app_control_uri_get_query(handle.get(), &query); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(query, nullptr); - - r = app_control_uri_get_host(handle.get(), &host); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - r = app_control_uri_get_port(handle.get(), &port); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - r = app_control_uri_get_user(handle.get(), &user); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - - EXPECT_EQ(std::string(host), "www.example.com"); - EXPECT_EQ(std::string(port), "123"); - EXPECT_EQ(std::string(user), "john.doe"); -} - -/* - * @testcase app_control_uri_create_n - * @description Creates a URI builder handle from an encoded URI string. - * The function returns a negative error value. - * @apicovered app_control_uri_create - */ -TEST_F(UriTest, app_control_uri_create_n) { - int r = app_control_uri_create(ENCODED_URI1, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - app_control_uri_h app_control_uri = nullptr; - r = app_control_uri_create(nullptr, &app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_destroy_p - * @description Destroys a URI handle. - * @apicovered app_control_uri_destroy - */ -TEST_F(UriTest, app_control_uri_destroy_p) { - int r = app_control_uri_destroy(uri_); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - uri_ = nullptr; -} - -/* - * @testcase app_control_uri_destroy_n - * @description Destroys a URI handle. - * The function returns a negative error value. - * @apicovered app_control_uri_destroy - */ -TEST_F(UriTest, app_control_uri_destroy_n) { - int r = app_control_uri_destroy(nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_encode_p - * @description Encodes a URI handle to string. - * @apicovered app_control_uri_encode - */ -TEST_F(UriTest, app_control_uri_encode_p) { - char *encoded_app_control_uri = nullptr; - int r = app_control_uri_encode(uri_, &encoded_app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_EQ(std::string(encoded_app_control_uri), ENCODED_URI1); - if (encoded_app_control_uri) - free(encoded_app_control_uri); -} - -/* - * @testcase app_control_uri_encode_n - * @description Encodes a URI handle to string. - * The function returns a nullptr. - * @apicovered app_control_uri_encode - */ -TEST_F(UriTest, app_control_uri_encode_n) { - char *encoded_app_control_uri; - int r = app_control_uri_encode(nullptr, &encoded_app_control_uri); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_scheme_p - * @description Gets a scheme component from a URI handle. - * @apicovered app_control_uri_get_scheme - */ -TEST_F(UriTest, app_control_uri_get_scheme_p) { - const char* scheme; - int r = app_control_uri_get_scheme(uri_, &scheme); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(scheme, nullptr); - EXPECT_EQ(std::string(scheme), "https"); -} - -/* - * @testcase app_control_uri_get_scheme_n - * @description Gets a scheme component from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_scheme - */ -TEST_F(UriTest, app_control_uri_get_scheme_n) { - const char* scheme; - int r = app_control_uri_get_scheme(nullptr, &scheme); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_authority_p - * @description Gets an authority component from a URI handle. - * @apicovered app_control_uri_get_authority - */ -TEST_F(UriTest, app_control_uri_get_authority_p) { - const char* auth; - int r = app_control_uri_get_authority(uri_, &auth); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(auth, nullptr); - EXPECT_EQ(std::string(auth), "//john.doe@www.example.com:123"); -} - -/* - * @testcase app_control_uri_get_authority_n - * @description Gets an authority component from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_authority - */ -TEST_F(UriTest, app_control_uri_get_authority_n) { - const char* auth; - int r = app_control_uri_get_authority(nullptr, &auth); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_path_p - * @description Gets a path component from a URI handle. - * @apicovered app_control_uri_get_path - */ -TEST_F(UriTest, app_control_uri_get_path_p) { - const char* path; - int r = app_control_uri_get_path(uri_, &path); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(path, nullptr); - EXPECT_EQ(std::string(path), "/forum/questions/"); -} - -/* - * @testcase app_control_uri_get_path_n - * @description Gets a path component from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_path - */ -TEST_F(UriTest, app_control_uri_get_path_n) { - const char* path; - int r = app_control_uri_get_path(nullptr, &path); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_fragment_p - * @description Gets a fragment component from a URI handle. - * @apicovered app_control_uri_get_fragment - */ -TEST_F(UriTest, app_control_uri_get_fragment_p) { - const char* fragment; - int r = app_control_uri_get_fragment(uri_, &fragment); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(fragment, nullptr); - EXPECT_EQ(std::string(fragment), "top"); -} - -/* - * @testcase app_control_uri_get_fragment_n - * @description Gets a fragment component from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_fragment - */ -TEST_F(UriTest, app_control_uri_get_fragment_n) { - const char* fragment; - int r = app_control_uri_get_fragment(nullptr, &fragment); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_query_p - * @description Gets a handle of the query component from a URI handle. - * @apicovered app_control_uri_get_query - */ -TEST_F(UriTest, app_control_uri_get_query_p) { - app_control_uri_query_h query = nullptr; - int r = app_control_uri_get_query(uri_, &query); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(query, nullptr); -} - -/* - * @testcase app_control_uri_get_query_n - * @description Gets a handle of the query component from a URI handle. - * The function returns a negative error value. - * @apicovered app_control_uri_get_query - */ -TEST_F(UriTest, app_control_uri_get_query_n) { - int r = app_control_uri_get_query(uri_, nullptr); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - app_control_uri_query_h query = nullptr; - r = app_control_uri_get_query(nullptr, &query); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_host_p - * @description Gets a host subcomponent from a URI handle. - * @apicovered app_control_uri_get_host - */ -TEST_F(UriTest, app_control_uri_get_host_p) { - const char* host; - int r = app_control_uri_get_host(uri_, &host); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(host, nullptr); - EXPECT_EQ(std::string(host), "www.example.com"); -} - -/* - * @testcase app_control_uri_get_host_n - * @description Gets a host subcomponent from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_host - */ -TEST_F(UriTest, app_control_uri_get_host_n) { - const char* host; - int r = app_control_uri_get_host(nullptr, &host); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_port_p - * @description Gets a port subcomponent from a URI handle. - * @apicovered app_control_uri_get_port - */ -TEST_F(UriTest, app_control_uri_get_port_p) { - const char* port; - int r = app_control_uri_get_port(uri_, &port); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(port, nullptr); - EXPECT_EQ(std::string(port), "123"); -} - -/* - * @testcase app_control_uri_get_port_n - * @description Gets a port subcomponent from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_port - */ -TEST_F(UriTest, app_control_uri_get_port_n) { - const char* port; - int r = app_control_uri_get_port(nullptr, &port); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_get_user_p - * @description Gets a user subcomponent from a URI handle. - * @apicovered app_control_uri_get_user - */ -TEST_F(UriTest, app_control_uri_get_user_p) { - const char* user; - int r = app_control_uri_get_user(uri_, &user); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(user, nullptr); - EXPECT_EQ(std::string(user), "john.doe"); -} - -/* - * @testcase app_control_uri_get_user_n - * @description Gets a user subcomponent from a URI handle. - * The function returns a nullptr. - * @apicovered app_control_uri_get_user - */ -TEST_F(UriTest, app_control_uri_get_user_n) { - const char* user; - int r = app_control_uri_get_user(nullptr, &user); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); -} - -/* - * @testcase app_control_uri_query_foreach_p - * @description Retrieves the key-value pairs attributes in the query component. - * @apicovered app_control_uri_query_foreach - */ -TEST_F(UriTest, app_control_uri_query_foreach_p) { - // Pre-condition: Gets the query handle - app_control_uri_query_h query = nullptr; - int r = app_control_uri_get_query(uri_, &query); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(query, nullptr); - - r = app_control_uri_query_foreach(query, - [](const char* key, const char* val, void* user_data) -> bool { - UriTest* p = static_cast(user_data); - if (!strcmp(key, "tag") && !strcmp(val, "networking")) - p->count_++; - else if (!strcmp(key, "order") && !strcmp(val, "newest")) - p->count_++; - return true; - }, this); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_EQ(count_, 2); -} - -/* - * @testcase app_control_uri_query_foreach_n - * @description Retrieves the key-value pairs attributes in the query component. - * The function returns a negative error value. - * @apicovered app_control_uri_query_foreach - */ -TEST_F(UriTest, app_control_uri_query_foreach_n) { - // Pre-condition: Gets the query handle - app_control_uri_query_h query = nullptr; - int r = app_control_uri_get_query(uri_, &query); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_NONE); - EXPECT_NE(query, nullptr); - - r = app_control_uri_query_foreach(query, nullptr, this); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - - r = app_control_uri_query_foreach(nullptr, - [](const char* key, const char* val, void* user_data) -> bool { - UriTest* p = static_cast(user_data); - if (!strcmp(key, "tag") && !strcmp(val, "networking")) - p->count_++; - else if (!strcmp(key, "order") && !strcmp(val, "newest")) - p->count_++; - return true; - }, this); - EXPECT_EQ(r, APP_CONTROL_URI_ERROR_INVALID_PARAMETER); - EXPECT_EQ(count_, 0); -}