From: Jihoon Kim Date: Wed, 21 Nov 2018 06:16:21 +0000 (+0900) Subject: Add autofill manager APIs X-Git-Tag: submit/tizen/20181210.023320~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=97c9aeb493622c079f8cfcbb5b9567fc17f4512b;p=platform%2Fcore%2Fuifw%2Fautofill.git Add autofill manager APIs Change-Id: I422bdba95403184a8063f701a6c4959c307d022c Signed-off-by: Jihoon Kim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 80113db..ce0756d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,9 @@ ADD_SUBDIRECTORY(client) ## Service library ## ADD_SUBDIRECTORY(service_lib) +## Manager library ## +ADD_SUBDIRECTORY(manager) + ## Server daemon ## ADD_SUBDIRECTORY(server) diff --git a/doc/autofill_manager_doc.h b/doc/autofill_manager_doc.h new file mode 100644 index 0000000..70eeaf4 --- /dev/null +++ b/doc/autofill_manager_doc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_AUTOFILL_MANAGER_DOC_H__ +#define __TIZEN_UIX_AUTOFILL_MANAGER_DOC_H__ + + +/** + * @ingroup CAPI_UIX_AUTOFILL_MODULE + * @defgroup CAPI_UIX_AUTOFILL_MANAGER_MODULE Autofill manager + * @brief The @ref CAPI_UIX_AUTOFILL_MANAGER_MODULE API provides the functions for getting the current autofill service or changing autofill service. + * @section CAPI_UIX_AUTOFILL_MANAGER_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_UIX_AUTOFILL_MANAGER_MODULE_OVERVIEW Overview + * Autofill is a feature that allows you to fill out commonly-entered information such as email, account and address in a text input field. email, account and address in a text input field. + * Autofill manager is a module for managing the installed autofill services. Application developers can use this module to get the current autofill service and changing the autofill service. + * @ref CAPI_UIX_AUTOFILL_MANAGER_MODULE functions are responsible for sending data for supporting autofill to the autofill service and receiving the commonly-entered data from the autofill service. + */ + + +#endif /* __TIZEN_UIX_AUTOFILL_MANAGER_DOC_H__ */ diff --git a/include/autofill_common.h b/include/autofill_common.h index 66696f3..40bc2e4 100644 --- a/include/autofill_common.h +++ b/include/autofill_common.h @@ -23,6 +23,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { @@ -33,19 +34,6 @@ extern "C" { * @{ */ -/** - * @brief Enumeration for autofill function error. - * - * @since_tizen 5.5 - */ -typedef enum { - AUTOFILL_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ - AUTOFILL_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ - AUTOFILL_ERROR_NOT_INITIALIZED = TIZEN_ERROR_AUTOFILL | 0x0001, /**< Not initialized */ - AUTOFILL_ERROR_OPERATION_FAILED = TIZEN_ERROR_AUTOFILL | 0x0002, /**< Operation failed */ - AUTOFILL_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ -} autofill_error_e; - /** * @brief Enumeration for autofill hint. * diff --git a/include/autofill_error.h b/include/autofill_error.h new file mode 100644 index 0000000..6ad20e4 --- /dev/null +++ b/include/autofill_error.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_AUTOFILL_ERROR_H__ +#define __TIZEN_UIX_AUTOFILL_ERROR_H__ + +/** + * @file autofill_error.h + * @brief This file contains autofill error enumeration. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup CAPI_UIX_AUTOFILL_COMMON_MODULE + * @{ + */ + +/** + * @brief Enumeration for autofill function error. + * + * @since_tizen 5.5 + */ +typedef enum { + AUTOFILL_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + AUTOFILL_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + AUTOFILL_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + AUTOFILL_ERROR_NOT_INITIALIZED = TIZEN_ERROR_AUTOFILL | 0x0001, /**< Not initialized */ + AUTOFILL_ERROR_OPERATION_FAILED = TIZEN_ERROR_AUTOFILL | 0x0002, /**< Operation failed */ + AUTOFILL_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ +} autofill_error_e; + +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_AUTOFILL_ERROR_H__ */ diff --git a/include/autofill_manager.h b/include/autofill_manager.h new file mode 100644 index 0000000..b8c56a5 --- /dev/null +++ b/include/autofill_manager.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_AUTOFILL_MANAGER_H__ +#define __TIZEN_UIX_AUTOFILL_MANAGER_H__ + +/** + * @file autofill_manager.h + * @brief This file contains autofill manager APIs and related enumeration. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @addtogroup CAPI_UIX_AUTOFILL_MANAGER_MODULE + * @{ + */ + +/** + * @brief Enumeration of connection status. + * @since_tizen 5.5 + */ +typedef enum { + AUTOFILL_MANAGER_CONNECTION_STATUS_CONNECTED = 0, /**< Connected */ + AUTOFILL_MANAGER_CONNECTION_STATUS_DISCONNECTED, /**< Disconnected */ + AUTOFILL_MANAGER_CONNECTION_STATUS_REJECTED, /**< Rejected */ +} autofill_manager_connection_status_e; + +/** + * @brief The autofill manager handle. + * @since_tizen 5.5 + */ +typedef struct autofill_manager_s *autofill_manager_h; + +/** + * @brief Called when the connection status is changed. + * @since_tizen 5.5 + * @remarks @a amh should not be freed and can be used only in the callback. + * @param[in] amh The autofill manager handle + * @param[in] status The connection status + * @param[in] user_data The user data passed from the callback function + * @see autofill_manager_connect() + */ +typedef void (*autofill_manager_connection_status_changed_cb)(autofill_manager_h amh, autofill_manager_connection_status_e status, void* user_data); + +/** + * @brief Called for each autofill service information. + * @since_tizen 5.5 + * @remarks @a app_id should not be freed and can be used only in the callback. + * @param[in] app_id The autofill service app ID + * @param[in] user_data The user data to be passed to the callback function + * @return @c true to continue with the next iteration of the loop, + * otherwise @c false to break out of the loop + * @pre autofill_manager_foreach_autofill_service() will invoke this callback. + * @see autofill_manager_foreach_autofill_service() + */ +typedef bool (*autofill_manager_autofill_service_cb)(const char *app_id, void *user_data); + +/** + * @brief Creates a handle for autofill manager. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @remarks If the function succeeds, @a amh handle must be released with autofill_manager_destroy(). + * @param[out] amh The autofill manager handle + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_OUT_OF_MEMORY Out of memory + * @see autofill_manager_destroy() + */ +int autofill_manager_create(autofill_manager_h *amh); + +/** + * @brief Destroys autofill manager handle. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @param[in] amh The autofill manager handle + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_NOT_INITIALIZED Not initialized + * @see autofill_manager_create() + */ +int autofill_manager_destroy(autofill_manager_h amh); + +/** + * @brief Connects to autofill manager daemon. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @param[in] amh The autofill manager handle + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_NOT_INITIALIZED Not initialized + * @retval #AUTOFILL_ERROR_OPERATION_FAILED Operation failure + */ +int autofill_manager_connect(autofill_manager_h amh, autofill_manager_connection_status_changed_cb callback, void *user_data); + +/** + * @platform + * @brief Sets autofill service. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @param[in] amh The autofill manager handle + * @param[in] app_id The autofill service app ID + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_NOT_INITIALIZED Not initialized + * @see autofill_manager_get_autofill_service() + */ +int autofill_manager_set_autofill_service(autofill_manager_h amh, const char *app_id); + +/** + * @brief Gets autofill service app ID. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @remarks @a service_app_id must be released using free(). + * @param[in] amh The autofill manager handle + * @param[out] service_app_id The autofill service app ID + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_NOT_INITIALIZED Not initialized + * @see autofill_manager_set_autofill_service() + */ +int autofill_manager_get_autofill_service(autofill_manager_h amh, char **service_app_id); + +/** + * @brief Retrieves all autofill services. + * @since_tizen 5.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/autofillmanager + * @param[in] amh The autofill manager handle + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #AUTOFILL_ERROR_NONE No error + * @retval #AUTOFILL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this function + * @retval #AUTOFILL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUTOFILL_ERROR_NOT_INITIALIZED Not initialized + * @retval #AUTOFILL_ERROR_OPERATION_FAILED Operation failure + */ +int autofill_manager_foreach_autofill_service(autofill_manager_h amh, autofill_manager_autofill_service_cb callback, void* user_data); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_AUTOFILL_MANAGER_H__ */ diff --git a/manager/CMakeLists.txt b/manager/CMakeLists.txt new file mode 100644 index 0000000..dd6a757 --- /dev/null +++ b/manager/CMakeLists.txt @@ -0,0 +1,107 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(project_prefix "capi") +SET(prefix "/usr") +SET(version "0.0.1") +SET(maintainer "Jihoon Kim ") +SET(description "Autofill Manager APIs") +SET(service "ui") +SET(submodule "autofill-manager") +SET(dependents "capi-base-common dlog eina glib-2.0 rpc-port cynara-client cynara-session") +SET(LIBDIR ${LIB_INSTALL_DIR}) + +SET(Services + "application" + "base" + "content" + "location" + "media" + "messaging" + "network" + "social" + "telephony" + "system" + "ui" + ) + +#FILE(STRINGS config.cfg configs REGEX "^ *[^#]") +FOREACH(lines ${configs}) +# MESSAGE(${lines}) + IF(${lines} MATCHES "([^=]*)=['\"](.*)['\"]") + SET(key ${CMAKE_MATCH_1}) + SET(value ${CMAKE_MATCH_2}) +# MESSAGE("${key} -> ${value}") + SET(${key} "${value}") + ENDIF() +ENDFOREACH(lines ${configs}) + +LIST(FIND Services ${service} sfind) + +IF( ${sfind} EQUAL -1 ) + MESSAGE(FATAL_ERROR "Service must be one of ") + FOREACH( s IN ${Services} ) + MESSAGE(FATAL_ERROR "[${s}]") + ENDFOREACH( s IN ${Services} ) +ENDIF( ${sfind} EQUAL -1 ) + +SET(fw_name "${project_prefix}-${service}-${submodule}") + +PROJECT(${fw_name} C) + +SET(CMAKE_INSTALL_PREFIX ${prefix}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(VERSION ${version}) + +SET(INC_DIR ../include .) +INCLUDE_DIRECTORIES(${INC_DIR}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_name} REQUIRED ${dependents}) +FOREACH(flag ${${fw_name}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -fpermissive") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") + +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DTIZEN_DEBUG") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib") + +aux_source_directory(. SOURCES) +aux_source_directory(../privilege_checker PRIV_SOURCES) +ADD_LIBRARY(${fw_name} SHARED ${SOURCES} ${PRIV_SOURCES}) + +TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS}) + +SET_TARGET_PROPERTIES(${fw_name} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 +) + +INSTALL(TARGETS ${fw_name} DESTINATION ${LIBDIR}) +INSTALL( + DIRECTORY ${INC_DIR}/ DESTINATION include + FILES_MATCHING + PATTERN "*_private.h" EXCLUDE + PATTERN "${INC_DIR}/*.h" + ) + +SET(PC_NAME ${fw_name}) +SET(PC_REQUIRED ${dependents}) +SET(PC_LDFLAGS -l${fw_name}) + +CONFIGURE_FILE( + capi-ui-autofill-manager.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIBDIR}/pkgconfig) diff --git a/manager/autofill_manager.c b/manager/autofill_manager.c new file mode 100644 index 0000000..d7fbf77 --- /dev/null +++ b/manager/autofill_manager.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2018 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 "autofill_manager_proxy.h" +#include "../privilege_checker/privilege_checker_private.h" + +#define AUTOFILL_DAEMON_APP_ID "org.tizen.autofill-daemon" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "AUTOFILL_MANAGER" + +struct autofill_manager_s { + rpc_port_proxy_AutofillManagerPort_h rpc_h; + autofill_manager_connection_status_changed_cb connection_callback; + void *connection_userdata; +}; + +static void __on_connected(rpc_port_proxy_AutofillManagerPort_h h, void *user_data) +{ + autofill_manager_h amh = user_data; + LOGI("[__RPC_PORT__] connected"); + + if (amh->connection_callback) + amh->connection_callback(amh, AUTOFILL_MANAGER_CONNECTION_STATUS_CONNECTED, amh->connection_userdata); +} + +//LCOV_EXCL_START +static void __on_disconnected(rpc_port_proxy_AutofillManagerPort_h h, void *user_data) +{ + autofill_manager_h amh = user_data; + LOGD("disconnected"); + + if (amh->connection_callback) + amh->connection_callback(amh, AUTOFILL_MANAGER_CONNECTION_STATUS_DISCONNECTED, amh->connection_userdata); + + amh->rpc_h = NULL; +} + +static void __on_rejected(rpc_port_proxy_AutofillManagerPort_h h, void *user_data) +{ + autofill_manager_h amh = user_data; + LOGD("rejected"); + + if (amh->connection_callback) + amh->connection_callback(amh, AUTOFILL_MANAGER_CONNECTION_STATUS_REJECTED, amh->connection_userdata); +} +//LCOV_EXCL_STOP + +EXPORT_API int autofill_manager_create(autofill_manager_h *amh) +{ + int ret; + + LOGD("autofill manager initialize"); + + if (!amh) { + LOGW("Invalid paramater"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + else { + LOGD("Succeed to check privilege"); + } + + struct autofill_manager_s *ams = (autofill_manager_h)calloc(1, sizeof(struct autofill_manager_s)); + if (!ams) + return AUTOFILL_ERROR_OUT_OF_MEMORY; + + rpc_port_proxy_AutofillManagerPort_callback_s rpc_callback = { + .connected = __on_connected, + .disconnected = __on_disconnected, + .rejected = __on_rejected + }; + + ret = rpc_port_proxy_AutofillManagerPort_create(AUTOFILL_DAEMON_APP_ID, &rpc_callback, ams, &ams->rpc_h); + if (ret != RPC_PORT_ERROR_NONE) { + LOGW("Failed to create rpc port. err = %d", ret); + free(ams); + return AUTOFILL_ERROR_OUT_OF_MEMORY; + } + + *amh = (autofill_manager_h)ams; + + return AUTOFILL_ERROR_NONE; +} + +EXPORT_API int autofill_manager_destroy(autofill_manager_h amh) +{ + LOGD("autofill manager deinitialize"); + + if (!amh) { + LOGW("Invalid paramater"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + amh->connection_callback = NULL; + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + else { + LOGD("Succeed to check privilege"); + } + + if (amh->rpc_h) { + rpc_port_proxy_AutofillManagerPort_destroy(amh->rpc_h); + amh->rpc_h = NULL; + } + + return AUTOFILL_ERROR_NONE; +} + +EXPORT_API int autofill_manager_connect(autofill_manager_h amh, autofill_manager_connection_status_changed_cb callback, void *user_data) +{ + LOGD("autofill manager connect"); + + int ret; + + if (!amh || !callback) { + LOGW("parameter is NULL\n"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + + if (!amh->rpc_h) { + LOGW("rpc handle is NULL"); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + + amh->connection_callback = callback; + amh->connection_userdata = user_data; + + ret = rpc_port_proxy_AutofillManagerPort_connect(amh->rpc_h); + switch (ret) { + case RPC_PORT_ERROR_PERMISSION_DENIED: + LOGW("permission error"); + break; + } + + if (ret != RPC_PORT_ERROR_NONE) { + LOGW("Failed to connect rpc port. err = %d", ret); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + + return AUTOFILL_ERROR_NONE; +} + +EXPORT_API int autofill_manager_set_autofill_service(autofill_manager_h amh, const char *app_id) +{ + LOGD("autofill manager set autofill service"); + + if (!amh || !app_id) { + LOGW("parameter is NULL"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + + if (!amh->rpc_h) { + LOGW("rpc handle is NULL"); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + + bool ret = rpc_port_proxy_AutofillManagerPort_invoke_set_autofill_service(amh->rpc_h, app_id); + if (ret == false) { + LOGW("Failed to send rpc port. err = %d", ret); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + return AUTOFILL_ERROR_NONE; +} + +EXPORT_API int autofill_manager_get_autofill_service(autofill_manager_h amh, char **service_app_id) +{ + LOGD("autofill manager get autofill service"); + + if (!amh || !service_app_id) { + LOGW("parameter is NULL"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + + if (!amh->rpc_h) { + LOGW("Not initialized"); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + + char *app_id = rpc_port_proxy_AutofillManagerPort_invoke_get_autofill_service(amh->rpc_h); + if (app_id) { + LOGD("service id : %s", app_id); + *service_app_id = strdup(app_id); + free(app_id); + return AUTOFILL_ERROR_NONE; + } else { + return AUTOFILL_ERROR_OPERATION_FAILED; + } +} + +EXPORT_API int autofill_manager_foreach_autofill_service(autofill_manager_h amh, autofill_manager_autofill_service_cb callback, void* user_data) +{ + int ret; + + if (!amh || !callback) { + LOGW("parameter is NULL"); + return AUTOFILL_ERROR_INVALID_PARAMETER; + } + + if (!check_privilege(AUTOFILL_MANAGER_PRIVILEGE)) { + LOGW("Permission denied"); + return AUTOFILL_ERROR_PERMISSION_DENIED; + } + + if (!amh->rpc_h) { + LOGW("rpc handle is NULL\n"); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + + rpc_port_list_string_h app_id_list; + rpc_port_list_string_create(&app_id_list); + ret = rpc_port_proxy_AutofillManagerPort_invoke_get_autofill_service_list(amh->rpc_h, &app_id_list); + if (ret == false) { + LOGW("Failed to send rpc port. err = %d", ret); + return AUTOFILL_ERROR_OPERATION_FAILED; + } + rpc_port_list_string_foreach_list_strings(app_id_list, callback, user_data); + + rpc_port_list_string_destroy(app_id_list); + + return AUTOFILL_ERROR_NONE; +} diff --git a/manager/capi-ui-autofill-manager.manifest b/manager/capi-ui-autofill-manager.manifest new file mode 100644 index 0000000..dfdc35c --- /dev/null +++ b/manager/capi-ui-autofill-manager.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/manager/capi-ui-autofill-manager.pc.in b/manager/capi-ui-autofill-manager.pc.in new file mode 100644 index 0000000..7740411 --- /dev/null +++ b/manager/capi-ui-autofill-manager.pc.in @@ -0,0 +1,14 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIBDIR@ +includedir=/usr/include + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} + diff --git a/packaging/capi-ui-autofill.spec b/packaging/capi-ui-autofill.spec index e99a588..4f31e5f 100644 --- a/packaging/capi-ui-autofill.spec +++ b/packaging/capi-ui-autofill.spec @@ -15,6 +15,10 @@ BuildRequires: pkgconfig(eina) BuildRequires: pkgconfig(efl) BuildRequires: pkgconfig(rpc-port) BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-preference) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -65,6 +69,24 @@ Requires: %{name} = %{version}-%{release} Autofill Service Library (Development) +%package -n capi-ui-autofill-manager +Summary: Autofill Manager Library +Group: Graphics & UI Framework/Input +Requires: %{name} = %{version}-%{release} + +%description -n capi-ui-autofill-manager +Autofill Manager Library + + +%package -n capi-ui-autofill-manager-devel +Summary: Autofill Manager Library (Development) +Group: Graphics & UI Framework/Input +Requires: %{name} = %{version}-%{release} + +%description -n capi-ui-autofill-manager-devel +Autofill Manager Library (Development) + + %package -n org.tizen.autofill-daemon Summary: Autofill Daemon application Group: Graphics & UI Framework/Input @@ -93,6 +115,15 @@ tidlc -s -l C -i tidl/autofill_service.tidl -o autofill_service_stub mv autofill_service_stub.h ./service_lib/ mv autofill_service_stub.c ./service_lib/ +tidlc -p -l C -i tidl/autofill_manager.tidl -o autofill_manager_proxy +mv autofill_manager_proxy.h ./manager/ +mv autofill_manager_proxy.c ./manager/ + +tidlc -s -l C -i tidl/autofill_manager.tidl -o autofill_manager_stub +mv autofill_manager_stub.h ./server/ +mv autofill_manager_stub.c ./server/ + + %build export CFLAGS+=" -DTIZEN_DEBUG_ENABLE -fvisibility=hidden -Werror" @@ -132,6 +163,7 @@ mkdir -p %{TZ_SYS_RO_APP}/org.tizen.autofill-daemon %files -n capi-ui-autofill-common-devel %{_includedir}/autofill_common*.h +%{_includedir}/autofill_error.h %{_libdir}/pkgconfig/capi-ui-autofill-common.pc %{_libdir}/libcapi-ui-autofill-common.so @@ -150,6 +182,17 @@ mkdir -p %{TZ_SYS_RO_APP}/org.tizen.autofill-daemon %{_libdir}/pkgconfig/capi-ui-autofill-service.pc %{_libdir}/libcapi-ui-autofill-service.so +%files -n capi-ui-autofill-manager +%manifest manager/capi-ui-autofill-manager.manifest +%{_libdir}/libcapi-ui-autofill-manager.so.* +%license LICENSE + +%files -n capi-ui-autofill-manager-devel +%{_includedir}/autofill_error.h +%{_includedir}/autofill_manager*.h +%{_libdir}/pkgconfig/capi-ui-autofill-manager.pc +%{_libdir}/libcapi-ui-autofill-manager.so + %files -n org.tizen.autofill-daemon %manifest server/org.tizen.autofill-daemon.manifest %{TZ_SYS_RO_PACKAGES}/org.tizen.autofill-daemon.xml diff --git a/privilege_checker/privilege_checker.c b/privilege_checker/privilege_checker.c new file mode 100644 index 0000000..bf13bf3 --- /dev/null +++ b/privilege_checker/privilege_checker.c @@ -0,0 +1,56 @@ +#include "privilege_checker_private.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +bool +check_privilege(const char *privilege) +{ + cynara *p_cynara = NULL; + FILE *fp = NULL; + char label_path[1024] = "/proc/self/attr/current"; + char smack_label[1024] = {'\0', }; + char uid[10] = {0,}; + + return true; //FIXME + + int ret = cynara_initialize(&p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + return false; + } + + if (!p_cynara) { + return false; + } + + fp = fopen(label_path, "r"); + if (fp != NULL) { + if (fread(smack_label, 1, sizeof(smack_label) - 1, fp) <= 0) { + LOGW("[check_privilege] fail to fread"); + } + fclose(fp); + } + + pid_t pid = getpid(); + snprintf(uid, 10, "%d", getuid()); + char *session = cynara_session_from_pid(pid); + ret = cynara_check(p_cynara, smack_label, session, uid, privilege); + if (session) + free(session); + + if (p_cynara) + cynara_finish(p_cynara); + + if (ret != CYNARA_API_ACCESS_ALLOWED) { + return false; + } + return true; +} diff --git a/privilege_checker/privilege_checker_private.h b/privilege_checker/privilege_checker_private.h new file mode 100644 index 0000000..c6b62ef --- /dev/null +++ b/privilege_checker/privilege_checker_private.h @@ -0,0 +1,10 @@ +#ifndef __PRIVILEGE_CHECKER_H +#define __PRIVILEGE_CHECKER_H + +#include + +#define AUTOFILL_MANAGER_PRIVILEGE "http://tizen.org/privilege/autofillmanager" + +bool check_privilege(const char *privilege); + +#endif /* __PRIVILEGE_CHECKER_H */ diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 03ad946..aba710e 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -3,7 +3,9 @@ PROJECT(autofill-daemon C) SET(SRCS main.c + autofill_config.c autofill_stub.c + autofill_manager_stub.c autofill_service_proxy.c ) @@ -12,6 +14,9 @@ pkg_check_modules(pkgs_daemon REQUIRED capi-appfw-service-application rpc-port glib-2.0 + capi-appfw-app-manager + capi-appfw-preference + eina ) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) diff --git a/server/autofill_config.c b/server/autofill_config.c new file mode 100644 index 0000000..c891f2b --- /dev/null +++ b/server/autofill_config.c @@ -0,0 +1,111 @@ + /* + * Copyright (c) 2018 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 "autofill_config.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "AUTOFILL_DAEMON" + +#define SETTING_ACTIVE_AUTOFILL_SERVICE "ActiveAutofillService" +#define AUTOFILL_SYSTEM_CONFIG_FILE "/etc/autofill/config" + +bool autofill_config_get_autofill_service_app_id(char **app_id) +{ + char *active_autofill_service_id = NULL; + FILE *pFile = NULL; + Eina_Strbuf *sb_key = NULL, *sb_value = NULL; + const char *key_str = NULL; + const char *value_str = NULL; + bool ret = false; + char strTemp[1024]; + + if (preference_get_string(SETTING_ACTIVE_AUTOFILL_SERVICE, &active_autofill_service_id) == PREFERENCE_ERROR_NONE) { + LOGD("preference active autofill service : %s", active_autofill_service_id); + *app_id = active_autofill_service_id; + return true; + } + + LOGD("Read from config"); + + pFile = fopen(AUTOFILL_SYSTEM_CONFIG_FILE, "r"); + if (pFile == NULL) + return false; + + while (fgets(strTemp, sizeof(strTemp), pFile) != NULL) + { + char **result_arr = eina_str_split(strTemp, "=", 0); + if (!result_arr) + continue; + + if (!result_arr[0]) { + free(result_arr); + continue; + } + + sb_key = eina_strbuf_new(); + eina_strbuf_append(sb_key, result_arr[0]); + eina_strbuf_trim(sb_key); + + key_str = eina_strbuf_string_get(sb_key); + if (key_str) { + if (strcmp(key_str, SETTING_ACTIVE_AUTOFILL_SERVICE) == 0) { + if (result_arr[1]) { + sb_value = eina_strbuf_new(); + eina_strbuf_append(sb_value, result_arr[1]); + eina_strbuf_trim(sb_value); + value_str = eina_strbuf_string_get(sb_value); + + if (app_id && value_str) { + *app_id = strdup(value_str); + ret = true; + } + + eina_strbuf_free(sb_value); + } + } + eina_strbuf_free(sb_key); + } + + /* Free the memory */ + free(result_arr[0]); + free(result_arr); + + if (ret) + break; + } /* end of while */ + + fclose(pFile); + + return ret; +} + +bool autofill_config_set_autofill_service_app_id(const char *app_id) +{ + if (preference_set_string(SETTING_ACTIVE_AUTOFILL_SERVICE, app_id) == PREFERENCE_ERROR_NONE) + return true; + + return false; +} + diff --git a/server/autofill_config.h b/server/autofill_config.h new file mode 100644 index 0000000..57eb00e --- /dev/null +++ b/server/autofill_config.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AUTOFILL_CONFIG_H__ +#define __AUTOFILL_CONFIG_H__ + +#include + +#define AUTOFILL_SERVICE_APP_ID "org.tizen.autofill-service" + +#ifdef __cplusplus +extern "C" { +#endif + +bool autofill_config_get_autofill_service_app_id(char **app_id); +bool autofill_config_set_autofill_service_app_id(const char *app_id); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __AUTOFILL_CONFIG_H__ */ diff --git a/server/main.c b/server/main.c index 6c9e316..57792b6 100644 --- a/server/main.c +++ b/server/main.c @@ -20,19 +20,23 @@ #include #include #include +#include #include "autofill_stub.h" #include "autofill_service_proxy.h" +#include "autofill_manager_stub.h" +#include "autofill_config.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "AUTOFILL_DAEMON" -#define AUTOFILL_SERVICE_APP_ID "org.tizen.autofill-service" static rpc_port_proxy_AutofillSvcPort_h rpc_h = NULL; +static int connect_service(); + typedef struct { char *app_id; @@ -59,7 +63,7 @@ get_autofill_client(const char *app_id) continue; } - if (strcmp(client->app_id, app_id) == 0) { + if (client->app_id && strcmp(client->app_id, app_id) == 0) { return client; } } @@ -116,14 +120,20 @@ static void __destroy_client(gpointer data) if (!handle) return; - if (handle->auth_info_cb) + if (handle->auth_info_cb) { rpc_port_AutofillAppPort_autofill_auth_info_received_cb_destroy(handle->auth_info_cb); + handle->auth_info_cb = NULL; + } - if (handle->fill_response_received_cb) + if (handle->fill_response_received_cb) { rpc_port_AutofillAppPort_autofill_fill_response_received_cb_destroy(handle->fill_response_received_cb); + handle->fill_response_received_cb = NULL; + } - if (handle->app_id) + if (handle->app_id) { free(handle->app_id); + handle->app_id = NULL; + } free(handle); } @@ -203,6 +213,18 @@ static void __message_unregister(rpc_port_stub_AutofillAppPort_context_h context __remove_client(context); } +static void __manager_create(rpc_port_stub_AutofillManagerPort_context_h context, + void *user_data) +{ + LOGD(""); +} + +static void __manager_terminate(rpc_port_stub_AutofillManagerPort_context_h context, + void *user_data) +{ + LOGD(""); +} + bool __view_info_item_cb(rpc_port_autofill_item_h items, void *user_data) { char *id = NULL; @@ -308,6 +330,11 @@ static int __auth_info_request_cb(rpc_port_stub_AutofillAppPort_context_h contex char *sender = NULL; autofill_client_s *sender_client; + if (!rpc_h) { + LOGW("Not initialized"); + return -1; + } + rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender); char *view_id = NULL; @@ -344,6 +371,11 @@ static int __autofill_fill_request_cb(rpc_port_stub_AutofillAppPort_context_h co char *sender = NULL; char *view_id = NULL; + if (!rpc_h) { + LOGW("Not initialized"); + return -1; + } + rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender); rpc_port_autofill_view_info_get_view_id(vi, &view_id); @@ -374,6 +406,11 @@ static int __commit_cb(rpc_port_stub_AutofillAppPort_context_h context, rpc_port char *sender = NULL; autofill_client_s *sender_client; + if (!rpc_h) { + LOGW("Not initialized"); + return -1; + } + rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender); if (sender) { LOGD("sender(%s)", sender); @@ -566,9 +603,105 @@ static void __on_rejected(rpc_port_proxy_AutofillSvcPort_h h, void *user_data) } //LCOV_EXCL_STOP +static bool __manager_set_autofill_service_cb(rpc_port_stub_AutofillManagerPort_context_h context, const char *app_id, void *user_data) +{ + LOGD("app id : %s", app_id); + + if (app_id) + autofill_config_set_autofill_service_app_id(app_id); + + if (rpc_h) { + LOGD("send terminate"); + // terminate service + rpc_port_proxy_AutofillSvcPort_invoke_request_terminate(rpc_h); + + int ret = rpc_port_proxy_AutofillSvcPort_destroy(rpc_h); + LOGD("ret : %d", ret); + } + + rpc_h = NULL; + + connect_service(); + + return true; +} + +static char * __manager_get_autofill_service_cb(rpc_port_stub_AutofillManagerPort_context_h context, void *user_data) +{ + if (!rpc_h) { + LOGW("Not initialized"); + return false; + } + + char *app_id; + autofill_config_get_autofill_service_app_id(&app_id); + + LOGD("app id : %s", app_id); + + return app_id; +} + +bool add_autofill_service_cb(app_info_h app_info, void *user_data) +{ + char *app_id = NULL; + rpc_port_list_string_h service_info_list = (rpc_port_list_string_h)user_data; + + int ret = app_info_get_app_id(app_info, &app_id); + if (ret != APP_MANAGER_ERROR_NONE) { + LOGW("app_info_get_app_id failed (%d)", ret); + return true; + } + + LOGD("Find autofill service : %s", app_id); + + rpc_port_list_string_add_list_strings(service_info_list, app_id); + + if (app_id) { + free(app_id); + } + + return true; +} + +static bool __manager_get_autofill_service_list_cb(rpc_port_stub_AutofillManagerPort_context_h context, rpc_port_list_string_h *service_info_list, void *user_data) +{ + int ret; + app_info_metadata_filter_h handle = NULL; + + // Get the Autofill service list + ret = app_info_metadata_filter_create(&handle); + if (ret != APP_MANAGER_ERROR_NONE) { + LOGW("app_info_metadata_filter_create failed (%d)", ret); + app_info_metadata_filter_destroy(handle); + return false; + } + + ret = app_info_metadata_filter_add(handle, "autofill-service", "true"); + if (ret != APP_MANAGER_ERROR_NONE) { + LOGW("app_info_metadata_filter_add failed (%d)", ret); + app_info_metadata_filter_destroy(handle); + return false; + } + + rpc_port_list_string_h app_id_list_h; + rpc_port_list_string_create(&app_id_list_h); + + ret = app_info_metadata_filter_foreach(handle, add_autofill_service_cb, app_id_list_h); + if (ret != APP_MANAGER_ERROR_NONE) { + LOGW("app_info_metadata_filter_foreach failed (%d)", ret); + } + + *service_info_list = app_id_list_h; + + app_info_metadata_filter_destroy(handle); + + return true; +} + static int connect_service() { int ret; + size_t service_id_len; rpc_port_proxy_AutofillSvcPort_callback_s rpc_callback = { .connected = __on_connected, @@ -581,13 +714,39 @@ static int connect_service() return RPC_PORT_ERROR_NONE; } - ret = rpc_port_proxy_AutofillSvcPort_create(AUTOFILL_SERVICE_APP_ID, &rpc_callback, NULL, &rpc_h); - if (ret != RPC_PORT_ERROR_NONE) { - LOGW("Failed to create rpc port. err = %d", ret); - return false; + char *active_autofill_service_id = NULL; + autofill_config_get_autofill_service_app_id(&active_autofill_service_id); + LOGD("autofill service : '%s'", active_autofill_service_id); + + if (!active_autofill_service_id) { + active_autofill_service_id = strdup(AUTOFILL_SERVICE_APP_ID); + } + + if (active_autofill_service_id) { + autofill_config_set_autofill_service_app_id(active_autofill_service_id); + service_id_len = strlen(active_autofill_service_id); + + if (service_id_len > 0) { + ret = rpc_port_proxy_AutofillSvcPort_create(active_autofill_service_id, &rpc_callback, NULL, &rpc_h); + } + free(active_autofill_service_id); + + if (service_id_len == 0) { + LOGD("No Autofill service to connect"); + return false; + } + + if (ret != RPC_PORT_ERROR_NONE) { + LOGW("Failed to create rpc port. err = %d", ret); + return false; + } } ret = rpc_port_proxy_AutofillSvcPort_connect(rpc_h); + if (ret != RPC_PORT_ERROR_NONE) { + LOGW("Failed to connect. err = %d", ret); + return false; + } return ret; } @@ -598,6 +757,7 @@ bool service_app_create(void *data) LOGD(""); int ret; + // register app port rpc_port_stub_AutofillAppPort_callback_s callback = { __message_create, __message_terminate, @@ -610,9 +770,24 @@ bool service_app_create(void *data) ret = rpc_port_stub_AutofillAppPort_register(&callback, NULL); if (ret != 0) - LOGI("Failed to register message"); + LOGI("Failed to register app port"); + else + LOGI("Succeeded to register app port"); + + // register manager port + rpc_port_stub_AutofillManagerPort_callback_s manager_callback = { + __manager_create, + __manager_terminate, + __manager_set_autofill_service_cb, + __manager_get_autofill_service_cb, + __manager_get_autofill_service_list_cb, + }; + + ret = rpc_port_stub_AutofillManagerPort_register(&manager_callback, NULL); + if (ret != 0) + LOGI("Failed to register manager port"); else - LOGI("Succeeded to register message"); + LOGI("Succeeded to register manager port"); connect_service(); diff --git a/tidl/autofill_manager.tidl b/tidl/autofill_manager.tidl new file mode 100644 index 0000000..f1ea517 --- /dev/null +++ b/tidl/autofill_manager.tidl @@ -0,0 +1,5 @@ +interface AutofillManagerPort { + bool set_autofill_service(string app_id); + string get_autofill_service(); + bool get_autofill_service_list(out list service_info_list); +}