--- /dev/null
+//
+// 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 <dlog.h>
+#include <errno.h>
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+#include <systemd/sd-login.h>
+
+#include <gum/gum-user.h>
+#include <gum/gum-user-service.h>
+#include <gum/common/gum-user-types.h>
+
+/* 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;
+}