Add autofill manager APIs 28/194028/22
authorJihoon Kim <jihoon48.kim@samsung.com>
Wed, 21 Nov 2018 06:16:21 +0000 (15:16 +0900)
committerJihoon Kim <jihoon48.kim@samsung.com>
Mon, 10 Dec 2018 02:00:38 +0000 (11:00 +0900)
Change-Id: I422bdba95403184a8063f701a6c4959c307d022c
Signed-off-by: Jihoon Kim <jihoon48.kim@samsung.com>
17 files changed:
CMakeLists.txt
doc/autofill_manager_doc.h [new file with mode: 0644]
include/autofill_common.h
include/autofill_error.h [new file with mode: 0644]
include/autofill_manager.h [new file with mode: 0644]
manager/CMakeLists.txt [new file with mode: 0644]
manager/autofill_manager.c [new file with mode: 0644]
manager/capi-ui-autofill-manager.manifest [new file with mode: 0644]
manager/capi-ui-autofill-manager.pc.in [new file with mode: 0644]
packaging/capi-ui-autofill.spec
privilege_checker/privilege_checker.c [new file with mode: 0644]
privilege_checker/privilege_checker_private.h [new file with mode: 0644]
server/CMakeLists.txt
server/autofill_config.c [new file with mode: 0644]
server/autofill_config.h [new file with mode: 0644]
server/main.c
tidl/autofill_manager.tidl [new file with mode: 0644]

index 80113db..ce0756d 100755 (executable)
@@ -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 (file)
index 0000000..70eeaf4
--- /dev/null
@@ -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 <autofill_manager.h>
+ *
+ * @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__ */
index 66696f3..40bc2e4 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <tizen.h>
+#include <autofill_error.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,19 +35,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.
  *
  * @since_tizen 5.5
diff --git a/include/autofill_error.h b/include/autofill_error.h
new file mode 100644 (file)
index 0000000..6ad20e4
--- /dev/null
@@ -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 (file)
index 0000000..b8c56a5
--- /dev/null
@@ -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 <tizen.h>
+#include <autofill_error.h>
+
+/**
+ * @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 (file)
index 0000000..dd6a757
--- /dev/null
@@ -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 <jihoon48.kim@samsung.com>")
+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 (file)
index 0000000..d7fbf77
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlog.h>
+#include <unistd.h>
+#include <autofill_manager.h>
+#include <rpc-port.h>
+#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 (file)
index 0000000..dfdc35c
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+  <domain name="_"/>
+ </request>
+</manifest>
diff --git a/manager/capi-ui-autofill-manager.pc.in b/manager/capi-ui-autofill-manager.pc.in
new file mode 100644 (file)
index 0000000..7740411
--- /dev/null
@@ -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}
+
index e99a588..4f31e5f 100644 (file)
@@ -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 (file)
index 0000000..bf13bf3
--- /dev/null
@@ -0,0 +1,56 @@
+#include "privilege_checker_private.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlog.h>
+
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-creds-socket.h>
+#include <cynara-session.h>
+
+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 (file)
index 0000000..c6b62ef
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __PRIVILEGE_CHECKER_H
+#define __PRIVILEGE_CHECKER_H
+
+#include <stdbool.h>
+
+#define AUTOFILL_MANAGER_PRIVILEGE "http://tizen.org/privilege/autofillmanager"
+
+bool check_privilege(const char *privilege);
+
+#endif /* __PRIVILEGE_CHECKER_H */
index 03ad946..aba710e 100644 (file)
@@ -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 (file)
index 0000000..c891f2b
--- /dev/null
@@ -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 <tizen.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <app_preference.h>
+#include <Eina.h>
+#include <dlog.h>
+
+#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 (file)
index 0000000..57eb00e
--- /dev/null
@@ -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 <stdbool.h>
+
+#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__ */
index 6c9e316..57792b6 100644 (file)
 #include <dlog.h>
 #include <glib.h>
 #include <rpc-port.h>
+#include <app_manager.h>
 
 #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 (file)
index 0000000..f1ea517
--- /dev/null
@@ -0,0 +1,5 @@
+interface AutofillManagerPort {
+    bool set_autofill_service(string app_id);
+    string get_autofill_service();
+    bool get_autofill_service_list(out list<string> service_info_list);
+}