From 06ee9cbc86b310c2ec5a9fdd9aa609c584d262a7 Mon Sep 17 00:00:00 2001 From: "sooyeon.kim" Date: Thu, 4 Oct 2018 22:53:18 +0900 Subject: [PATCH] Add assistant info parser Change-Id: I7c081c3b9575234cd40a856ea917afc4a1477f80 Signed-off-by: sooyeon.kim --- CMakeLists.txt | 4 + assistant-parser/CMakeLists.txt | 32 + assistant-parser/src/ma_assistant_parser.c | 953 +++++++++++++++++++++ multi-assistant.info | 1 + packaging/multi-assistant.spec | 2 + 5 files changed, 992 insertions(+) create mode 100644 assistant-parser/CMakeLists.txt create mode 100644 assistant-parser/src/ma_assistant_parser.c create mode 100644 multi-assistant.info diff --git a/CMakeLists.txt b/CMakeLists.txt index 47158bc..be437e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,9 @@ ADD_SUBDIRECTORY(include) ## Client library ## ADD_SUBDIRECTORY(client) +## Assistant parser ## +ADD_SUBDIRECTORY(assistant-parser) + ## Server daemon ## #ADD_SUBDIRECTORY(server) @@ -71,3 +74,4 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/org.tizen.multiassistant.mauiclient.service DE INSTALL(FILES ${CMAKE_SOURCE_DIR}/ma-server.conf DESTINATION /etc/dbus-1/session.d) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/multi-assistant.info DESTINATION ${TZ_SYS_RO_SHARE}/parser-plugins) diff --git a/assistant-parser/CMakeLists.txt b/assistant-parser/CMakeLists.txt new file mode 100644 index 0000000..1652240 --- /dev/null +++ b/assistant-parser/CMakeLists.txt @@ -0,0 +1,32 @@ +pkg_check_modules(parser-pkgs REQUIRED + capi-base-common + dlog + glib-2.0 + libxml-2.0 + pkgmgr-info + pkgmgr-installer + libtzplatform-config +) + +FOREACH(flag ${parser-pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET (SRCS + src/ma_assistant_parser.c +) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall" ) +SET(extapi "-fvisibility=hidden") + +## SET C COMPILER FLAGS +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${extapi}") + +## SET LINKER FLAGS +SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed") + +## Create Library +ADD_LIBRARY ("${PROJECT_NAME}_assistant_parser" SHARED ${SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}_assistant_parser" ${parser-pkgs_LDFLAGS} ) + +INSTALL(TARGETS "${PROJECT_NAME}_assistant_parser" DESTINATION "/etc/package-manager/parserlib/metadata") diff --git a/assistant-parser/src/ma_assistant_parser.c b/assistant-parser/src/ma_assistant_parser.c new file mode 100644 index 0000000..b78890d --- /dev/null +++ b/assistant-parser/src/ma_assistant_parser.c @@ -0,0 +1,953 @@ +// +// Copyright (c) 2018 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Define EXPORT_API */ +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ma-assistant-parser" + +#define MA_TAG_ASSISTANT_BASE "multi-assistant" +#define MA_TAG_ASSISTANT_NAME "name" +#define MA_TAG_ASSISTANT_ID "id" +#define MA_TAG_ASSISTANT_ICON_PATH "icon-path" +#define MA_TAG_ASSISTANT_LANGUAGE_SET "languages" +#define MA_TAG_ASSISTANT_LANGUAGE "lang" +#define MA_TAG_ASSISTANT_WAKEUP_WORD_SET "wakeup-words" +#define MA_TAG_ASSISTANT_WAKEUP_WORD "wakeup-word" + +#define MA_CONFIG_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.multiassistant") +#define MA_HOME tzplatform_mkpath(TZ_USER_HOME, "share/.multiassistant/ma") +#define MA_ASSISTANT_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.multiassistant/ma/1.0") +#define MA_ASSISTANT_INFO tzplatform_mkpath(TZ_USER_HOME, "share/.multiassistant/ma/1.0/assistant-info") + +#define MA_GLOBAL_CONFIG_BASE "/etc/skel/share/.multiassistant" +#define MA_GLOBAL_HOME "/etc/skel/share/.multiassistant/ma" +#define MA_GLOBAL_ASSISTANT_BASE "/etc/skel/share/.multiassistant/ma/1.0" +#define MA_GLOBAL_ASSISTANT_INFO "/etc/skel/share/.multiassistant/ma/1.0/assistant-info" + +#define MA_METADATA_ASSISTANT_NAME "http://tizen.org/metadata/multi-assistant/name" +#define MA_METADATA_ASSISTANT_ICON_PATH "http://tizen.org/metadata/multi-assistant/icon_path" +#define MA_METADATA_ASSISTANT_WAKEUP_WORD "http://tizen.org/metadata/multi-assistant/wakeup_word" +#define MA_METADATA_LANGUAGE "http://tizen.org/metadata/multi-assistant/language" + + +/* Define Macro */ +#define FREE(x) { if (NULL != x) { free(x); x = NULL; } } +#define G_FREE(x) { if (NULL != x) { g_free(x); x = NULL; } } +#define XML_FREE(x) { if (NULL != x) { xmlFreeDoc(x); x = NULL; } } + + +typedef struct metadata { + const char *key; + const char *value; +} metadata; + +static xmlDocPtr g_doc; +GumUser *g_guser = NULL; +uid_t g_uid = 301; // app_fw +gid_t g_gid = 301; // app_fw +GumUserType g_ut = GUM_USERTYPE_NONE; +gchar *g_user_type = NULL; + +char *g_dir_config_base = NULL; +char *g_dir_home = NULL; +char *g_dir_assistant_base = NULL; +char *g_dir_assistant_info = NULL; + + +static int __create_assistant_info_xml(const char *pkgid) +{ + LOGD("=== Create assistant info doc"); + + g_doc = xmlNewDoc((xmlChar*)"1.0"); + if (NULL == g_doc) { + LOGE("[ERROR] Fail to new doc"); + return -1; + } + LOGD("==="); + + return 0; +} + +static int __save_assistant_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t gid) +{ + LOGD("=== Save assistant info doc"); + char *dir_config_base = NULL; + char *dir_home = NULL; + char *dir_assistant_base = NULL; + char *dir_assistant_info = NULL; + + if (NULL == ut || (NULL != ut && 0 == strncmp(ut, "none", strlen("none")))) { + LOGE("[ERROR] Usertype is NONE"); + return -1; + } + + uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + uid_t tmp_uid = 0; + gid_t tmp_gid = 0; + LOGD("uid(%d)", uid); + + if (globalapp_uid == uid) { + /* Global app */ + dir_config_base = strdup(MA_GLOBAL_CONFIG_BASE); + dir_home = strdup(MA_GLOBAL_HOME); + dir_assistant_base = strdup(MA_GLOBAL_ASSISTANT_BASE); + dir_assistant_info = strdup(MA_GLOBAL_ASSISTANT_INFO); + tmp_uid = 301; // app_fw + tmp_gid = 301; // app_fw + } else { + /* User app, Guest app, Security app */ + if (NULL != g_dir_config_base) + dir_config_base = strdup(g_dir_config_base); + if (NULL != g_dir_home) + dir_home = strdup(g_dir_home); + if (NULL != g_dir_assistant_base) + dir_assistant_base = strdup(g_dir_assistant_base); + if (NULL != g_dir_assistant_info) + dir_assistant_info = strdup(g_dir_assistant_info); + + tmp_uid = uid; + tmp_gid = gid; + } + + if (NULL == dir_config_base || NULL == dir_home || NULL == dir_assistant_base || NULL == dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + return -1; + } + + LOGD("[DEBUG] dir_assistant_info(%s)", dir_assistant_info); + + /* Make directories */ + int fd = -1; +// if (0 != access(dir_config_base, F_OK)) { + fd = open(dir_config_base, O_DIRECTORY); + if (-1 == fd) { + LOGE("[INFO] No directory : %s, errno : %d", dir_config_base, errno); + if (0 != mkdir(dir_config_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_config_base, errno); + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + return -1; + } else { + LOGD("Success to make directory : %s", dir_config_base); + if (0 != chown(dir_config_base, tmp_uid, tmp_gid)) { + LOGD("[ERROR] Fail to change user and group, errno : %d", errno); + } else { + LOGD("[DEBUG] Success to change user and group"); + } + } + } else { + close(fd); + } + +// if (0 != access(dir_home, F_OK)) { + fd = open(dir_home, O_DIRECTORY); + if (-1 == fd) { + LOGE("[INFO] No directory : %s, errno : %d", dir_home, errno); + if (0 != mkdir(dir_home, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_home, errno); + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + return -1; + } else { + LOGD("Success to make directory : %s", dir_home); + if (0 != chown(dir_home, tmp_uid, tmp_gid)) { + LOGD("[ERROR] Fail to change user and group, errno : %d", errno); + } else { + LOGD("[DEBUG] Success to change user and group"); + } + } + } else { + close(fd); + } + +// if (0 != access(dir_assistant_base, F_OK)) { + fd = open(dir_assistant_base, O_DIRECTORY); + if (-1 == fd) { + LOGE("[INFO] No directory : %s, errno : %d", dir_assistant_base, errno); + if (0 != mkdir(dir_assistant_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_assistant_base, errno); + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + return -1; + } else { + LOGD("Success to make directory : %s", dir_assistant_base); + if (0 != chown(dir_assistant_base, tmp_uid, tmp_gid)) { + LOGD("[ERROR] Fail to change user and group, errno : %d", errno); + } else { + LOGD("[DEBUG] Success to change user and group"); + } + } + } else { + close(fd); + } + +// if (0 != access(dir_assistant_info, F_OK)) { + fd = open(dir_assistant_info, O_DIRECTORY); + if (-1 == fd) { + LOGE("[INFO] No directory : %s, errno : %d", dir_assistant_info, errno); + if (0 != mkdir(dir_assistant_info, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_assistant_info, errno); + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + return -1; + } else { + LOGD("Success to make directory : %s", dir_assistant_info); + if (0 != chown(dir_assistant_info, tmp_uid, tmp_gid)) { + LOGD("[ERROR] Fail to change user and group, errno : %d", errno); + } else { + LOGD("[DEBUG] Success to change user and group"); + } + } + } else { + close(fd); + } + + char path[256] = {'\0',}; + snprintf(path, 256, "%s/%s.xml", dir_assistant_info, pkgid); + int ret = xmlSaveFormatFile(path, g_doc, 1); + LOGD("xmlSaveFile (%d)", ret); + if (0 == ret) { + if (0 != chown(path, tmp_uid, tmp_gid)) { + LOGD("[ERROR] Fail to change user and group"); + } else { + LOGD("[DEBUG] Success to change user and group"); + } + } + + FREE(dir_config_base) + FREE(dir_home) + FREE(dir_assistant_base) + FREE(dir_assistant_info) + + LOGD("==="); + + return 0; +} + +static int __remove_assistant_info_xml(const char *pkgid, gchar *ut, uid_t uid) +{ + LOGD("=== Remove assistant info doc"); + + char *dir_assistant_info = NULL; + + if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) { + LOGE("[ERROR] Usertype is NONE"); + return -1; + } + + uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + + LOGD("uid(%d)", uid); + + if (globalapp_uid == uid) { + /* Global app */ + dir_assistant_info = strdup(MA_GLOBAL_ASSISTANT_INFO); + } else { + /* User app, Guest app, Security app */ + if (NULL != g_dir_assistant_info) + dir_assistant_info = strdup(g_dir_assistant_info); + } + + if (NULL == dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + return -1; + } + + LOGD("[DEBUG] dir_assistant_info(%s)", dir_assistant_info); + + char path[256] = {'\0',}; + snprintf(path, 256, "%s/%s.xml", dir_assistant_info, pkgid); + if (0 == access(path, F_OK)) { + LOGD("Remove assistant info xml(%s)", path); + if (0 != remove(path)) { + LOGE("[ERROR] Fail to remove assistant info xml(%s)", path); + } + } + + FREE(dir_assistant_info) + + LOGD("==="); + + return 0; +} + +static void __insert_language_from_metadata(xmlNodePtr root, const char *language) +{ + LOGD("==== Insert language"); + + char* lang = NULL; + + if (NULL == root || NULL == language) { + LOGE("Invalid parameter, root(%p), language(%s)", root, language); + return; + } + + char *tmp_lang, *tmp_free; + tmp_free = tmp_lang = strdup(language); + xmlNodePtr languages_node = NULL; + xmlNodePtr lang_node = NULL; + + languages_node = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_LANGUAGE_SET); + + lang = strsep(&tmp_lang, ","); + while (NULL != lang) { + LOGD("lang (%s)", lang); + lang_node = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_LANGUAGE); + xmlNodeSetContent(lang_node, (const xmlChar*)lang); + xmlAddChild(languages_node, lang_node); + lang = strsep(&tmp_lang, ","); + } + xmlAddChild(root, languages_node); + + FREE(tmp_free) +} + +static void __insert_wakeup_word_from_metadata(xmlNodePtr root, const char *wakeup_word) +{ + LOGD("==== Insert wakeup words"); + + char* wakeup = NULL; + + if (NULL == root || NULL == wakeup_word) { + LOGE("Invalid parameter, root(%p), language(%s)", root, wakeup_word); + return; + } + + char *tmp_wakeup, *tmp_free; + tmp_free = tmp_wakeup = strdup(wakeup_word); + xmlNodePtr wakeups_node = NULL; + xmlNodePtr wakeup_node = NULL; + + wakeups_node = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_WAKEUP_WORD_SET); + + wakeup = strsep(&tmp_wakeup, ","); + while (NULL != wakeup) { + LOGD("wakeup word (%s)", wakeup); + wakeup_node = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_WAKEUP_WORD); + xmlNodeSetContent(wakeup_node, (const xmlChar*)wakeup); + xmlAddChild(wakeups_node, wakeup_node); + wakeup = strsep(&tmp_wakeup, ","); + } + xmlAddChild(root, wakeups_node); + + FREE(tmp_free) +} + +static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *list) +{ + GList *iter = NULL; + metadata *md = NULL; + + __create_assistant_info_xml(pkgid); + + xmlNodePtr root = NULL; + xmlNodePtr cur = NULL; + + root = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_BASE); + + if (NULL == root) { + LOGE("[ERROR] Fail to get new node"); + return -1; + } + xmlDocSetRootElement(g_doc, root); + + iter = g_list_first(list); + while (NULL != iter) { + md = (metadata *)iter->data; + if (NULL != md && NULL != md->key && NULL != md->value) { + LOGD(" - key(%s) value(%s)", md->key, md->value); + if (!strncmp(md->key, MA_METADATA_LANGUAGE, strlen(MA_METADATA_LANGUAGE))) { + __insert_language_from_metadata(root, md->value); + } else if (!strncmp(md->key, MA_METADATA_ASSISTANT_WAKEUP_WORD, strlen(MA_METADATA_ASSISTANT_WAKEUP_WORD))) { + __insert_wakeup_word_from_metadata(root, md->value); + } else if (!strncmp(md->key, MA_METADATA_ASSISTANT_ICON_PATH, strlen(MA_METADATA_ASSISTANT_ICON_PATH))) { + cur = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_ICON_PATH); + xmlNodeSetContent(cur, (const xmlChar*)md->value); + xmlAddChild(root, cur); + } else if (!strncmp(md->key, MA_METADATA_ASSISTANT_NAME, strlen(MA_METADATA_ASSISTANT_NAME))) { + cur = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_NAME); + xmlNodeSetContent(cur, (const xmlChar*)md->value); + xmlAddChild(root, cur); + } else { + LOGW("[WARNING] Unknown metadata type"); + } + } + iter = g_list_next(iter); + } + + cur = xmlNewNode(NULL, (const xmlChar*)MA_TAG_ASSISTANT_ID); + xmlNodeSetContent(cur, (const xmlChar*)appid); + xmlAddChild(root, cur); + + LOGD(""); + return 0; +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA INSTALL"); + LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list)); + + int ret = -1; + ret = pkgmgr_installer_info_get_target_uid(&g_uid); + if (ret < 0) { + LOGE("[ERROR] Fail to get target uid"); + return 0; + } else { + LOGD("uid(%d)", g_uid); + printf("[Parser Debug][DEBUG] uid(%d)", g_uid); + } + + uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + if (globalapp_uid == g_uid) { + g_user_type = g_strdup("admin"); + } else { + g_guser = gum_user_get_sync(g_uid, FALSE); + if (NULL == g_guser) { + LOGE("[ERROR] g_guser is NULL"); + return -1; + } + + g_object_get(G_OBJECT(g_guser), "gid", &g_gid, NULL); + g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL); + g_user_type = g_strdup(gum_user_type_to_string(g_ut)); + } + + if (NULL == g_user_type) { + LOGE("[ERROR] Fail to allocate memory"); + if (NULL != g_guser) { + g_object_unref(g_guser); + g_guser = NULL; + } + return -1; + } + + if (0 == strcmp(g_user_type, "none")) { + /* GUM_USERTYPE_NONE */ + LOGE("[ERROR] Fail to get target uid"); + g_object_unref(g_guser); + g_guser = NULL; + G_FREE(g_user_type) + return -1; + } + + if (globalapp_uid == g_uid) { + /* global directory */ + LOGD("[DEBUG] usertype: %s", g_user_type); + if (0 >= g_list_length(list)) { + LOGE("[ERROR] No assistant metadata"); + G_FREE(g_user_type) + return 0; + } + + if (0 != __write_metadata_inxml(pkgid, appid, list)) { + LOGE("[ERROR] Fail to write metadata in the xml"); + XML_FREE(g_doc); + G_FREE(g_user_type) + return -1; + } + + /* Save in /etc/skel/share/ */ + g_dir_config_base = strdup(MA_GLOBAL_CONFIG_BASE); + g_dir_home = strdup(MA_GLOBAL_HOME); + g_dir_assistant_base = strdup(MA_GLOBAL_ASSISTANT_BASE); + g_dir_assistant_info = strdup(MA_GLOBAL_ASSISTANT_INFO); + + if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_assistant_base || NULL == g_dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return -1; + } + + if (0 != __save_assistant_info_xml(pkgid, g_user_type, g_uid, g_gid)) { + LOGE("[ERROR] Fail to make assistant info file"); + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return -1; + } + + /* Get user data by using libgum */ + + GumUserService *gus = NULL; + GumUserList *users = NULL; + GumUserList *iter = NULL; + GumUser *user = NULL; + gchar **query; + GumUserType gumut = GUM_USERTYPE_NONE; + gchar *user_type = NULL; + + uid_t uid; + gid_t gid; + gchar *home_dir = NULL; + + gus = gum_user_service_create_sync(TRUE); + if (!gus) { + LOGE("Failed to create gum user service"); + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return -1; + } + + query = g_strsplit("admin,normal", ",", -1); + + users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query); + g_strfreev(query); + + if (!users) { + LOGD("NO users"); + g_object_unref(gus); + gus = NULL; + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return 0; + } + + /* Make new user list */ + + iter = users; + while (iter != NULL) { + user = (GumUser*) iter->data; + g_object_get(G_OBJECT(user), "uid", &uid, NULL); + G_FREE(home_dir) + + g_object_get(G_OBJECT(user), "gid", &gid, NULL); + g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL); + g_object_get(G_OBJECT(user), "usertype", &gumut, NULL); + user_type = g_strdup(gum_user_type_to_string(gumut)); + if (NULL == user_type) { + gum_user_service_list_free(users); + G_FREE(home_dir) + g_object_unref(gus); + gus = NULL; + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return -1; + } + + LOGD("[DEBUG] user info"); + if (NULL != home_dir) { + LOGD("[DEBUG] uid(%d), gid(%d), user_type(%s), home_dir(%s)", uid, gid, user_type, home_dir); + + g_dir_config_base = (char*)calloc(strlen(home_dir) + 23, sizeof(char)); + g_dir_home = (char*)calloc(strlen(home_dir) + 26, sizeof(char)); + g_dir_assistant_base = (char*)calloc(strlen(home_dir) + 30, sizeof(char)); + g_dir_assistant_info = (char*)calloc(strlen(home_dir) + 45, sizeof(char)); + + if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_assistant_base || NULL == g_dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + gum_user_service_list_free(users); + g_object_unref(gus); + gus = NULL; + G_FREE(g_user_type) + G_FREE(user_type) + G_FREE(home_dir) + return -1; + } + snprintf(g_dir_config_base, strlen(home_dir) + 23, "%s/share/.multiassistant", home_dir); + snprintf(g_dir_home, strlen(home_dir) + 26, "%s/share/.multiassistant/ma", home_dir); + snprintf(g_dir_assistant_base, strlen(home_dir) + 30, "%s/share/.multiassistant/ma/1.0", home_dir); + snprintf(g_dir_assistant_info, strlen(home_dir) + 45, "%s/share/.multiassistant/ma/1.0/assistant-info", home_dir); + + LOGD("[DEBUG] g_dir_assistant_info(%s)", g_dir_assistant_info); + + if (0 != __save_assistant_info_xml(pkgid, user_type, uid, gid)) { + LOGE("[ERROR] Fail to make assistant info file"); + } + + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + + G_FREE(home_dir) + } + + G_FREE(user_type) + iter = g_list_next(iter); + } + + gum_user_service_list_free(users); + g_object_unref(gus); + gus = NULL; + } else { + /* user directory */ + LOGD("[DEBUG] usertype: %s", g_user_type); + + ret = tzplatform_set_user(g_uid); + if (ret < 0) { + LOGE("[ERROR] Invalid uid"); + g_object_unref(g_guser); + g_guser = NULL; + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return 0; + } else { + LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/")); + printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/")); + } + + if (0 >= g_list_length(list)) { + LOGE("[ERROR] No assistant metadata"); + g_object_unref(g_guser); + g_guser = NULL; + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + G_FREE(g_user_type) + return 0; + } + + if (0 != __write_metadata_inxml(pkgid, appid, list)) { + LOGE("[ERROR] Fail to write metadata in the xml"); + XML_FREE(g_doc); + g_object_unref(g_guser); + g_guser = NULL; + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + G_FREE(g_user_type) + return -1; + } + + g_dir_config_base = strdup(MA_CONFIG_BASE); + g_dir_home = strdup(MA_HOME); + g_dir_assistant_base = strdup(MA_ASSISTANT_BASE); + g_dir_assistant_info = strdup(MA_ASSISTANT_INFO); + + if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_assistant_base || NULL == g_dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + XML_FREE(g_doc); + g_object_unref(g_guser); + g_guser = NULL; + G_FREE(g_user_type) + return -1; + } + + if (0 != __save_assistant_info_xml(pkgid, g_user_type, g_uid, g_gid)) { + LOGE("[ERROR] Fail to make assistant info file"); + XML_FREE(g_doc); + if (NULL != g_guser) { + g_object_unref(g_guser); + g_guser = NULL; + } + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + G_FREE(g_user_type) + return -1; + } + } + + XML_FREE(g_doc); + if (NULL != g_guser) { + g_object_unref(g_guser); + g_guser = NULL; + } + G_FREE(g_user_type) + + FREE(g_dir_config_base) + FREE(g_dir_home) + FREE(g_dir_assistant_base) + FREE(g_dir_assistant_info) + + return 0; +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA UNINSTALL"); + LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list)); + + int ret = -1; + ret = pkgmgr_installer_info_get_target_uid(&g_uid); + if (ret < 0) { + LOGE("[ERROR] Fail to get target uid"); + return 0; + } else { + LOGD("uid(%d)", g_uid); + printf("[Parser Debug][DEBUG] uid(%d)", g_uid); + } + + uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + if (globalapp_uid == g_uid) { + g_user_type = g_strdup("admin"); + } else { + g_guser = gum_user_get_sync(g_uid, FALSE); + if (NULL == g_guser) { + LOGE("[ERROR] g_guser is NULL"); + return -1; + } + + g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL); + g_user_type = g_strdup(gum_user_type_to_string(g_ut)); + } + + if (NULL == g_user_type) { + LOGE("[ERROR] Fail to allocate memory"); + if (NULL != g_guser) { + g_object_unref(g_guser); + g_guser = NULL; + } + return -1; + } + + if (0 == strcmp(g_user_type, "none")) { + /* GUM_USERTYPE_NONE */ + LOGE("[ERROR] Fail to get target uid"); + g_object_unref(g_guser); + g_guser = NULL; + G_FREE(g_user_type) + return -1; + } + + if (globalapp_uid == g_uid) { + /* global directory */ + LOGD("[DEBUG] usertype: %s", g_user_type); + + /* Remove files in /etc/skel/share/ */ + g_dir_assistant_info = strdup(MA_GLOBAL_ASSISTANT_INFO); + if (NULL == g_dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + G_FREE(g_user_type) + return -1; + } + + if (0 != __remove_assistant_info_xml(pkgid, g_user_type, g_uid)) { + LOGE("[ERROR] Fail to remove assistant info file"); + } + + /* Get user data by using libgum */ + + GumUserService *gus = NULL; + GumUserList *users = NULL; + GumUserList *iter = NULL; + GumUser *user = NULL; + gchar **query; + GumUserType gumut = GUM_USERTYPE_NONE; + gchar *user_type = NULL; + + uid_t uid; + gchar *home_dir = NULL; + + GList *md_iter = NULL; + metadata *md = NULL; + + gus = gum_user_service_create_sync(TRUE); + if (!gus) { + LOGE("Failed to create gum user service"); + G_FREE(g_user_type) + return -1; + } + + query = g_strsplit("admin,normal", ",", -1); + + users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query); + g_strfreev(query); + + if (!users) { + LOGD("NO users"); + g_object_unref(gus); + gus = NULL; + G_FREE(g_user_type) + return 0; + } + + /* Make new user list */ + + iter = users; + while (iter != NULL) { + user = (GumUser*) iter->data; + g_object_get(G_OBJECT(user), "uid", &uid, NULL); + G_FREE(home_dir) + g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL); + g_object_get(G_OBJECT(user), "usertype", &gumut, NULL); + user_type = g_strdup(gum_user_type_to_string(gumut)); + if (NULL == user_type) { + gum_user_service_list_free(users); + G_FREE(home_dir) + g_object_unref(gus); + gus = NULL; + return -1; + } + + if (NULL != home_dir) { + g_dir_assistant_info = (char*)calloc(strlen(home_dir) + 45, sizeof(char)); + if (NULL == g_dir_assistant_info) { + gum_user_service_list_free(users); + G_FREE(home_dir) + g_object_unref(gus); + gus = NULL; + G_FREE(user_type) + return -1; + } + + snprintf(g_dir_assistant_info, strlen(home_dir) + 45, "%s/share/.multiassistant/ma/1.0/assistant-info", home_dir); + + md_iter = g_list_first(list); + while (NULL != md_iter) { + md = (metadata *)md_iter->data; + LOGD(" - key(%s) value(%s)", md->key, md->value); + md_iter = g_list_next(md_iter); + } + + if (0 != __remove_assistant_info_xml(pkgid, user_type, uid)) { + LOGE("[ERROR] Fail to remove assistant info file"); + } + + G_FREE(home_dir) + G_FREE(g_dir_assistant_info) + } + G_FREE(user_type) + + LOGD("Finish release memory"); + iter = g_list_next(iter); + LOGD("Finish next iter"); + } + + gum_user_service_list_free(users); + g_object_unref(gus); + gus = NULL; + } else { + /* user directory */ + LOGD("[DEBUG] usertype: %s", g_user_type); + + ret = tzplatform_set_user(g_uid); + if (ret < 0) { + LOGE("[ERROR] Invalid uid"); + g_object_unref(g_guser); + g_guser = NULL; + G_FREE(g_user_type) + return -1; + } else { + LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/")); + printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/")); + } + + g_dir_assistant_info = strdup(MA_ASSISTANT_INFO); + if (NULL == g_dir_assistant_info) { + LOGE("[ERROR] Fail to allocate memory"); + g_object_unref(g_guser); + g_guser = NULL; + G_FREE(g_user_type) + return -1; + } + + if (0 != __remove_assistant_info_xml(pkgid, g_user_type, g_uid)) { + LOGE("[ERROR] Fail to remove assistant info file"); + } + + } + + if (NULL != g_guser) { + g_object_unref(g_guser); + g_guser = NULL; + } + G_FREE(g_user_type) + + FREE(g_dir_assistant_info) + + LOGD(""); + return 0; +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA UPGRADE"); + LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list)); + + PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list); + PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list); + + LOGD(""); + return 0; +} diff --git a/multi-assistant.info b/multi-assistant.info new file mode 100644 index 0000000..5b5eac4 --- /dev/null +++ b/multi-assistant.info @@ -0,0 +1 @@ +type="metadata";name="http://tizen.org/metadata/multi-assistant";path="/etc/package-manager/parserlib/metadata/libma_assistant_parser.so" diff --git a/packaging/multi-assistant.spec b/packaging/multi-assistant.spec index f2580de..70e4a89 100644 --- a/packaging/multi-assistant.spec +++ b/packaging/multi-assistant.spec @@ -91,6 +91,8 @@ mkdir -p %{_libdir}/multiassistant/ma %{_libdir}/libma_ui.so %{TZ_SYS_RO_SHARE}/multiassistant/ma/1.0/ma-config.xml %{TZ_SYS_RO_SHARE}/dbus-1/services/org.tizen.multiassistant* +%{TZ_SYS_RO_SHARE}/parser-plugins/multi-assistant.info +%{TZ_SYS_RO_ETC}/package-manager/parserlib/metadata/libma_assistant_parser.so* /etc/dbus-1/session.d/ma-server.conf %files devel -- 2.34.1