Add assistant info parser 76/190676/4 accepted/tizen/5.0/unified/20181102.022500 accepted/tizen/unified/20181010.061722 submit/tizen/20181005.114143 submit/tizen_5.0/20181101.000005
authorsooyeon.kim <sooyeon.kim@samsung.com>
Thu, 4 Oct 2018 13:53:18 +0000 (22:53 +0900)
committersooyeon.kim <sooyeon.kim@samsung.com>
Fri, 5 Oct 2018 10:47:31 +0000 (19:47 +0900)
Change-Id: I7c081c3b9575234cd40a856ea917afc4a1477f80
Signed-off-by: sooyeon.kim <sooyeon.kim@samsung.com>
CMakeLists.txt
assistant-parser/CMakeLists.txt [new file with mode: 0644]
assistant-parser/src/ma_assistant_parser.c [new file with mode: 0644]
multi-assistant.info [new file with mode: 0644]
packaging/multi-assistant.spec

index 47158bc17932133f66c9fa6f61e9a004c48b8635..be437e94bbc53057cbc4f66296d5fda2a74f7774 100644 (file)
@@ -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 (file)
index 0000000..1652240
--- /dev/null
@@ -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 (file)
index 0000000..b78890d
--- /dev/null
@@ -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 <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;
+}
diff --git a/multi-assistant.info b/multi-assistant.info
new file mode 100644 (file)
index 0000000..5b5eac4
--- /dev/null
@@ -0,0 +1 @@
+type="metadata";name="http://tizen.org/metadata/multi-assistant";path="/etc/package-manager/parserlib/metadata/libma_assistant_parser.so"
index f2580de6e21d349c595314ef228e8235b61bf44e..70e4a89502e3f240b2aa0b41d8a8450ac6476ddc 100644 (file)
@@ -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