Add widget-plugin-parser source codes 52/53552/1 accepted/tizen/mobile/20151210.083439 accepted/tizen/tv/20151210.083510 accepted/tizen/wearable/20151210.083521 submit/tizen/20151210.063423
authorSangyoon Jang <s89.jang@samsung.com>
Wed, 18 Nov 2015 04:28:10 +0000 (13:28 +0900)
committerSangyoon Jang <s89.jang@samsung.com>
Tue, 8 Dec 2015 02:34:15 +0000 (11:34 +0900)
note that data structures and related functions
at 'widget_plugin_parser_internal.h' could be separated

Change-Id: I0b236b9701572a43818b3b804b7057b3c22b7d85
Signed-off-by: Sangyoon Jang <s89.jang@samsung.com>
CMakeLists.txt
packaging/libwidget_service.spec
parser/CMakeLists.txt [new file with mode: 0644]
parser/widget.sql [new file with mode: 0644]
parser/widget_plugin_parser.c [new file with mode: 0644]
parser/widget_plugin_parser_db.c [new file with mode: 0644]
parser/widget_plugin_parser_internal.c [new file with mode: 0644]
parser/widget_plugin_parser_internal.h [new file with mode: 0644]
parser/widget_plugin_parser_pkgmgr_interface.c [new file with mode: 0644]

index af447ea..04d74d5 100644 (file)
@@ -122,4 +122,6 @@ ENDIF (WAYLAND_SUPPORT)
 
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION /usr/share/license RENAME "lib${PROJECT_NAME}")
 
+ADD_SUBDIRECTORY(parser)
+
 # End of a file
index 490947a..3088406 100644 (file)
@@ -24,6 +24,8 @@ BuildRequires: pkgconfig(bundle)
 BuildRequires: pkgconfig(capi-base-common)
 BuildRequires: pkgconfig(libdrm)
 BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(libxml-2.0)
 
 %if %{with wayland}
 BuildRequires: pkgconfig(wayland-client)
@@ -80,15 +82,25 @@ export WAYLAND_SUPPORT=Off
 export X11_SUPPORT=On
 %endif
 
+sqlite3 .widget.db < ./parser/widget.sql
+
 %cmake . -DWAYLAND_SUPPORT=${WAYLAND_SUPPORT} -DX11_SUPPORT=${X11_SUPPORT}
 make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
 %make_install
-mkdir -p %{buildroot}/%{_datarootdir}/license
+mkdir -p %{buildroot}%{_datarootdir}/license
+mkdir -p %{buildroot}%{TZ_SYS_DB}
+mkdir -p %{buildroot}%{_sysconfdir}/skel/.applications/dbspace
+
+install -m 0644 .widget.db %{buildroot}%{TZ_SYS_DB}
+install -m 0644 .widget.db %{buildroot}%{_sysconfdir}/skel/.applications/dbspace
 
 %post -n %{name} -p /sbin/ldconfig
+chsmack -a "User::Home" %{TZ_SYS_DB}/.widget.db
+chsmack -a "User::Home" %{_sysconfdir}/skel/.applications/dbspace/.widget.db
+
 %postun -n %{name} -p /sbin/ldconfig
 
 %files -n %{name}
@@ -96,6 +108,9 @@ mkdir -p %{buildroot}/%{_datarootdir}/license
 %defattr(-,root,root,-)
 %{_libdir}/libwidget_service.so*
 %{_datarootdir}/license/libwidget_service
+%{_sysconfdir}/package-manager/parserlib/libwidget-application.so
+%{_sysconfdir}/skel/.applications/dbspace/.widget.db
+%{TZ_SYS_DB}/.widget.db
 
 %files devel
 %manifest %{name}.manifest
diff --git a/parser/CMakeLists.txt b/parser/CMakeLists.txt
new file mode 100644 (file)
index 0000000..95c5697
--- /dev/null
@@ -0,0 +1,26 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(widget-plugin-parser C)
+
+SET(SRCS
+       widget_plugin_parser.c
+       widget_plugin_parser_db.c
+       widget_plugin_parser_internal.c
+       widget_plugin_parser_pkgmgr_interface.c
+       )
+
+pkg_check_modules(PKGS REQUIRED
+       glib-2.0
+       sqlite3
+       libxml-2.0
+       dlog
+       libtzplatform-config
+       )
+FOREACH(FLAGS ${PKGS_CFLAGS})
+       SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
+ENDFOREACH(FLAGS)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fPIC")
+
+ADD_LIBRARY(widget-application MODULE ${SRCS})
+
+INSTALL(TARGETS widget-application DESTINATION ${SYSCONF_INSTALL_DIR}/package-manager/parserlib/)
diff --git a/parser/widget.sql b/parser/widget.sql
new file mode 100644 (file)
index 0000000..6984494
--- /dev/null
@@ -0,0 +1,40 @@
+PRAGMA tizen_version = 30; /* Tizen 3.0 */
+PRAGMA db_version = 1;
+PRAGMA journal_mode = PERSIST;
+PRAGMA foreign_keys = ON;
+
+BEGIN EXCLUSIVE TRANSACTION;
+
+CREATE TABLE widget_class (
+  classid       TEXT NOT NULL,
+  update_period INTEGER DEFAULT 0,
+  setup_appid   TEXT,
+  appid         TEXT NOT NULL,
+  pkgid         TEXT NOT NULL,
+  PRIMARY KEY(classid)
+);
+
+CREATE TABLE support_size (
+  classid TEXT NOT NULL,
+  preview TEXT NOT NULL,
+  frame   INTEGER DEFAULT 0,
+  width   INTEGER NOT NULL,
+  height  INTEGER NOT NULL,
+  FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE
+);
+
+CREATE TABLE label (
+  classid TEXT NOT NULL,
+  locale  TEXT DEFAULT 'No Locale',
+  label   TEXT NOT NULL,
+  FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE
+);
+
+CREATE TABLE icon (
+  classid TEXT NOT NULL,
+  locale  TEXT DEFAULT 'No Locale',
+  icon    TEXT NOT NULL,
+  FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE
+);
+
+COMMIT TRANSACTION;
diff --git a/parser/widget_plugin_parser.c b/parser/widget_plugin_parser.c
new file mode 100644 (file)
index 0000000..e68c0e4
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2015  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <libxml/tree.h>
+#include <glib.h>
+
+#include <dlog.h>
+
+#include "widget_plugin_parser_internal.h"
+
+enum widget_tag {
+       TAG_WIDGET_APPLICATION = 1,
+       TAG_WIDGET_CLASS,
+       TAG_LABEL,
+       TAG_ICON,
+       TAG_SUPPORT_SIZE,
+};
+
+struct tag_map {
+       char *name;
+       enum widget_tag tag;
+};
+
+struct tag_map map[] = {
+       { "widget-application", TAG_WIDGET_APPLICATION },
+       { "widget-class", TAG_WIDGET_CLASS },
+       { "label", TAG_LABEL },
+       { "icon", TAG_ICON },
+       { "support-size", TAG_SUPPORT_SIZE }
+};
+static GHashTable *tag_table;
+
+int widget_plugin_parser_init(void)
+{
+       int i;
+
+       if (tag_table)
+               return 0;
+
+       tag_table = g_hash_table_new(g_int_hash, g_str_equal);
+       if (tag_table == NULL)
+               return -1;
+
+       for (i = 0; i < (sizeof(map) / sizeof(struct tag_map)); i++)
+               g_hash_table_insert(tag_table, map[i].name,
+                               (gpointer)map[i].tag);
+
+       return 0;
+}
+
+int widget_plugin_parser_fini(void)
+{
+       if (!tag_table)
+               return 0;
+
+       g_hash_table_destroy(tag_table);
+       tag_table = NULL;
+
+       return 0;
+}
+
+static char *_get_attribute(xmlNode *node, const char *name)
+{
+       xmlChar *val;
+       char *attr = NULL;
+
+       val = xmlGetProp(node, (const xmlChar *)name);
+       if (val) {
+               attr = strdup((char *)val);
+               xmlFree(val);
+       }
+
+       return attr;
+}
+
+static enum widget_tag _get_tag(xmlNode *node)
+{
+       return (enum widget_tag)g_hash_table_lookup(tag_table, node->name);
+}
+
+static int _parse_support_size(xmlNode *node, GList **sizes)
+{
+       char *val;
+       struct support_size *size;
+       char *tok;
+       char *ptr;
+
+       if (node->children == NULL || node->children->content == NULL)
+               return -1;
+
+       size = calloc(1, sizeof(struct support_size));
+       if (size == NULL)
+               return -1;
+
+       val = strdup((char *)node->children->content);
+       tok = strtok_r(val, "xX", &ptr);
+       if (tok == NULL) {
+               free(size);
+               return -1;
+       }
+       size->width = atoi(tok);
+       tok = strtok_r(NULL, "xX", &ptr);
+       if (tok == NULL) {
+               free(size);
+               return -1;
+       }
+       size->height = atoi(tok);
+       free(val);
+
+       size->preview = _get_attribute(node, "preview");
+       val = _get_attribute(node, "frame");
+       if (val && !strcasecmp(val, "true")) {
+               size->frame = true;
+               free(val);
+       }
+
+       *sizes = g_list_append(*sizes, size);
+
+       return 0;
+}
+
+static int _parse_icon(xmlNode *node, GList **icons)
+{
+       struct icon *icon;
+
+       if (node->children == NULL || node->children->content == NULL)
+               return -1;
+
+       icon = calloc(1, sizeof(struct icon));
+       if (icon == NULL)
+               return -1;
+
+       icon->icon = strdup((char *)node->children->content);
+       icon->lang = _get_attribute(node, "lang");
+
+       *icons = g_list_append(*icons, icon);
+
+       return 0;
+}
+
+static int _parse_label(xmlNode *node, GList **labels)
+{
+       struct label *label;
+
+       if (node->children == NULL || node->children->content == NULL)
+               return -1;
+
+       label = calloc(1, sizeof(struct label));
+       if (label == NULL)
+               return -1;
+
+       label->label = strdup((char *)node->children->content);
+       label->lang = _get_attribute(node, "lang");
+
+       *labels = g_list_append(*labels, label);
+
+       return 0;
+}
+
+static int _parse_widget_class(xmlNode *node, const char *appid, GList **apps)
+{
+       char *val;
+       xmlNode *tmp;
+       struct widget_class *wc;
+       char buf[128];
+
+       wc = calloc(1, sizeof(struct widget_class));
+       if (wc == NULL)
+               return -1;
+       wc->appid = strdup(appid);
+
+       val = _get_attribute(node, "classid");
+       if (val == NULL) {
+               free(wc);
+               return -1;
+       }
+       snprintf(buf, sizeof(buf), "%s@%s", val, appid);
+       free(val);
+       wc->classid = strdup(buf);
+
+       val = _get_attribute(node, "update-period");
+       if (val)
+               wc->update_period = atoi(val);
+       free(val);
+
+       wc->setup_appid = _get_attribute(node, "setup-appid");
+
+       for (tmp = node->children; tmp; tmp = tmp->next) {
+               switch (_get_tag(tmp)) {
+               case TAG_SUPPORT_SIZE:
+                       if (_parse_support_size(tmp, &wc->support_size)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               case TAG_ICON:
+                       if (_parse_icon(tmp, &wc->icon)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               case TAG_LABEL:
+                       if (_parse_label(tmp, &wc->label)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               default:
+                       /* unexpected tag */
+                       continue;
+               }
+       }
+
+       *apps = g_list_append(*apps, wc);
+
+       return 0;
+}
+
+static int _parse_widget_application(xmlNode *node, GList **list)
+{
+       char *val;
+       xmlNode *tmp;
+       struct widget_class *wc;
+
+       wc = calloc(1, sizeof(struct widget_class));
+       if (wc == NULL)
+               return -1;
+
+       val = _get_attribute(node, "appid");
+       if (val == NULL) {
+               free(wc);
+               return -1;
+       }
+       wc->appid = val;
+       wc->classid = strdup(wc->appid);
+
+       val = _get_attribute(node, "update-period");
+       if (val)
+               wc->update_period = atoi(val);
+
+       wc->setup_appid = _get_attribute(node, "setup-appid");
+
+       for (tmp = node->children; tmp; tmp = tmp->next) {
+               switch (_get_tag(tmp)) {
+               case TAG_SUPPORT_SIZE:
+                       if (_parse_support_size(tmp, &wc->support_size)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               case TAG_ICON:
+                       if (_parse_icon(tmp, &wc->icon)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               case TAG_LABEL:
+                       if (_parse_label(tmp, &wc->label)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+                       break;
+               case TAG_WIDGET_CLASS:
+                       if (_parse_widget_class(tmp, wc->appid, list)) {
+                               _free_widget_class((gpointer)wc);
+                               return -1;
+                       }
+               default:
+                       continue;
+               }
+       }
+
+       *list = g_list_append(*list, wc);
+
+       return 0;
+}
+
+GList *widget_plugin_parser_parse_manifest(xmlDocPtr doc)
+{
+       xmlNode *root;
+       xmlNode *tmp;
+       GList *list = NULL;
+
+       if (!tag_table) {
+               LOGE("parser is not initialized");
+               return NULL;
+       }
+
+       if (doc == NULL) {
+               LOGE("invalid parameter");
+               return NULL;
+       }
+
+       root = xmlDocGetRootElement(doc);
+       if (root == NULL) {
+               LOGE("failed to get root element");
+               return NULL;
+       }
+
+       for (tmp = root->children; tmp; tmp = tmp->next) {
+               if (_get_tag(tmp) != TAG_WIDGET_APPLICATION)
+                       continue;
+
+               if (_parse_widget_application(tmp, &list)) {
+                       LOGE("parse failed");
+                       return NULL;
+               }
+       }
+
+       return list;
+}
diff --git a/parser/widget_plugin_parser_db.c b/parser/widget_plugin_parser_db.c
new file mode 100644 (file)
index 0000000..4d2c5c0
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2015  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <sqlite3.h>
+
+#include <dlog.h>
+
+#include "widget_plugin_parser_internal.h"
+
+static int _bind_text(sqlite3_stmt *stmt, int idx, const char *text)
+{
+       if (text)
+               return sqlite3_bind_text(stmt, idx, text, -1, SQLITE_STATIC);
+       else
+               return sqlite3_bind_null(stmt, idx);
+}
+
+static int _insert_support_size(sqlite3 *db, const char *classid, GList *sizes)
+{
+       int ret;
+       static const char query[] =
+               "INSERT INTO support_size "
+               "(classid, preview, frame, width, height) "
+               "VALUES (?, ?, ?, ?, ?)";
+       GList *tmp;
+       struct support_size *size;
+       sqlite3_stmt *stmt = NULL;
+       int idx;
+
+       for (tmp = sizes; tmp; tmp = tmp->next) {
+               size = (struct support_size *)tmp->data;
+               ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+               if (ret != SQLITE_OK) {
+                       LOGE("prepare error: %s", sqlite3_errmsg(db));
+                       return -1;
+               }
+
+               idx = 1;
+               _bind_text(stmt, idx++, classid);
+               _bind_text(stmt, idx++, size->preview);
+               sqlite3_bind_int(stmt, idx++, size->frame);
+               sqlite3_bind_int(stmt, idx++, size->width);
+               sqlite3_bind_int(stmt, idx++, size->height);
+
+               ret = sqlite3_step(stmt);
+               if (ret != SQLITE_DONE) {
+                       LOGE("step error: %s", sqlite3_errmsg(db));
+                       sqlite3_finalize(stmt);
+                       return -1;
+               }
+
+               sqlite3_reset(stmt);
+               sqlite3_clear_bindings(stmt);
+       }
+
+       if (stmt)
+               sqlite3_finalize(stmt);
+
+       return 0;
+}
+
+static int _insert_label(sqlite3 *db, const char *classid, GList *labels)
+{
+       int ret;
+       static const char query[] =
+               "INSERT INTO label (classid, locale, label) "
+               "VALUES (?, ?, ?)";
+       GList *tmp;
+       struct label *label;
+       sqlite3_stmt *stmt = NULL;
+       int idx;
+
+       for (tmp = labels; tmp; tmp = tmp->next) {
+               label = (struct label *)tmp->data;
+               ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+               if (ret != SQLITE_OK) {
+                       LOGE("prepare error: %s", sqlite3_errmsg(db));
+                       return -1;
+               }
+
+               idx = 1;
+               _bind_text(stmt, idx++, classid);
+               _bind_text(stmt, idx++, label->lang);
+               _bind_text(stmt, idx++, label->label);
+
+               ret = sqlite3_step(stmt);
+               if (ret != SQLITE_DONE) {
+                       LOGE("step error: %s", sqlite3_errmsg(db));
+                       sqlite3_finalize(stmt);
+                       return -1;
+               }
+
+               sqlite3_reset(stmt);
+               sqlite3_clear_bindings(stmt);
+       }
+
+       if (stmt)
+               sqlite3_finalize(stmt);
+
+       return 0;
+}
+
+static int _insert_icon(sqlite3 *db, const char *classid, GList *icons)
+{
+       int ret;
+       static const char query[] =
+               "INSERT INTO icon (classid, locale, icon) "
+               "VALUES (?, ?, ?)";
+       GList *tmp;
+       struct icon *icon;
+       sqlite3_stmt *stmt = NULL;
+       int idx;
+
+       for (tmp = icons; tmp; tmp = tmp->next) {
+               icon = (struct icon *)tmp->data;
+               ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+               if (ret != SQLITE_OK) {
+                       LOGE("prepare error: %s", sqlite3_errmsg(db));
+                       return -1;
+               }
+
+               idx = 1;
+               _bind_text(stmt, idx++, classid);
+               _bind_text(stmt, idx++, icon->lang);
+               _bind_text(stmt, idx++, icon->icon);
+
+               ret = sqlite3_step(stmt);
+               if (ret != SQLITE_DONE) {
+                       LOGE("step error: %s", sqlite3_errmsg(db));
+                       sqlite3_finalize(stmt);
+                       return -1;
+               }
+
+               sqlite3_reset(stmt);
+               sqlite3_clear_bindings(stmt);
+       }
+
+       if (stmt)
+               sqlite3_finalize(stmt);
+
+       return 0;
+}
+
+static int _insert_widget_class(sqlite3 *db, const char *pkgid, GList *wcs)
+{
+       int ret;
+       static const char query[] =
+               "INSERT INTO widget_class (classid, update_period, "
+               "setup_appid, appid, pkgid) "
+               "VALUES (?, ?, ?, ?, ?)";
+       GList *tmp;
+       struct widget_class *wc;
+       sqlite3_stmt *stmt = NULL;
+       int idx;
+
+       for (tmp = wcs; tmp; tmp = tmp->next) {
+               wc = (struct widget_class *)tmp->data;
+               ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+               if (ret != SQLITE_OK) {
+                       LOGE("prepare error: %s", sqlite3_errmsg(db));
+                       return -1;
+               }
+
+               idx = 1;
+               _bind_text(stmt, idx++, wc->classid);
+               sqlite3_bind_int(stmt, idx++, wc->update_period);
+               _bind_text(stmt, idx++, wc->setup_appid);
+               _bind_text(stmt, idx++, wc->appid);
+               _bind_text(stmt, idx++, pkgid);
+
+               ret = sqlite3_step(stmt);
+               if (ret != SQLITE_DONE) {
+                       LOGE("step error: %s", sqlite3_errmsg(db));
+                       break;
+               }
+
+               sqlite3_reset(stmt);
+               sqlite3_clear_bindings(stmt);
+
+               if (_insert_support_size(db, wc->classid, wc->support_size))
+                       return -1;
+               if (_insert_label(db, wc->classid, wc->label))
+                       return -1;
+               if (_insert_icon(db, wc->classid, wc->icon))
+                       return -1;
+       }
+
+       if (stmt)
+               sqlite3_finalize(stmt);
+
+       return 0;
+}
+
+int widget_parser_db_insert_widget_class(const char *pkgid, GList *widget_list)
+{
+       int ret;
+       sqlite3 *db;
+
+       db = _open_db(getuid(), false);
+       if (db == NULL)
+               return -1;
+
+       if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
+               LOGE("begin transaction error");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       ret = _insert_widget_class(db, pkgid, widget_list);
+       if (ret) {
+               LOGE("failed to insert widget class data");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
+               LOGE("begin transaction error");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       _close_db(db);
+
+       return 0;
+}
+
+static int _remove_widget_class(sqlite3 *db, const char *pkgid)
+{
+       int ret;
+       static const char query[] =
+               "DELETE FROM widget_class WHERE pkgid=?";
+       sqlite3_stmt *stmt = NULL;
+
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+       if (ret != SQLITE_OK) {
+               LOGE("prepare error: %s", sqlite3_errmsg(db));
+               return -1;
+       }
+
+       _bind_text(stmt, 1, pkgid);
+
+       ret = sqlite3_step(stmt);
+       if (ret != SQLITE_DONE) {
+               LOGE("step error: %s", sqlite3_errmsg(db));
+               sqlite3_finalize(stmt);
+               return -1;
+       }
+
+       sqlite3_finalize(stmt);
+
+       return 0;
+}
+
+int widget_parser_db_remove_widget_class(const char *pkgid)
+{
+       int ret;
+       sqlite3 *db;
+
+       db = _open_db(getuid(), false);
+       if (db == NULL)
+               return -1;
+
+       if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
+               LOGE("begin transaction error");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       ret = _remove_widget_class(db, pkgid);
+       if (ret) {
+               LOGE("failed to remove widget class data");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
+               LOGE("begin transaction error");
+               sqlite3_close_v2(db);
+               return -1;
+       }
+
+       _close_db(db);
+
+       return 0;
+}
diff --git a/parser/widget_plugin_parser_internal.c b/parser/widget_plugin_parser_internal.c
new file mode 100644 (file)
index 0000000..ddc5239
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2015  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <sqlite3.h>
+
+#include <dlog.h>
+#include <tzplatform_config.h>
+
+#include "widget_plugin_parser_internal.h"
+
+void _free_support_size(gpointer data)
+{
+       struct support_size *size = (struct support_size *)data;
+
+       if (size == NULL)
+               return;
+
+       free(size->preview);
+       free(size);
+}
+
+void _free_label(gpointer data)
+{
+       struct label *label = (struct label *)data;
+
+       if (label == NULL)
+               return;
+
+       free(label->label);
+       free(label->lang);
+       free(label);
+}
+
+void _free_icon(gpointer data)
+{
+       struct icon *icon = (struct icon *)data;
+
+       if (icon == NULL)
+               return;
+
+       free(icon->icon);
+       free(icon->lang);
+       free(icon);
+}
+
+void _free_widget_class(gpointer data)
+{
+       struct widget_class *wc = (struct widget_class *)data;
+
+       if (wc == NULL)
+               return;
+
+       free(wc->classid);
+       free(wc->setup_appid);
+       free(wc->appid);
+
+       g_list_free_full(wc->support_size, _free_support_size);
+       g_list_free_full(wc->label, _free_label);
+       g_list_free_full(wc->icon, _free_icon);
+
+       free(wc);
+}
+
+#define ROOT_USER 0
+#define GLOBALAPP_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+static int _is_global(uid_t uid)
+{
+       if (uid == ROOT_USER || uid == GLOBALAPP_USER)
+               return 1;
+       else
+               return 0;
+}
+
+static char *_get_db_path(uid_t uid)
+{
+       const char *path;
+
+       if (!_is_global(uid))
+               tzplatform_set_user(uid);
+
+       path = tzplatform_mkpath(_is_global(uid) ?
+                       TZ_SYS_DB : TZ_USER_DB, ".widget.db");
+
+       tzplatform_reset_user();
+
+       return strdup(path);
+}
+
+sqlite3 *_open_db(uid_t uid, bool readonly)
+{
+       int ret;
+       sqlite3 *db;
+       char *path;
+
+       path = _get_db_path(uid);
+
+       if (access(path, F_OK) == -1) {
+               LOGD("db(%s) does not exist, create one", path);
+               return NULL;
+       }
+
+       ret = sqlite3_open_v2(path, &db,
+                       readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE,
+                       NULL);
+       if (ret != SQLITE_OK) {
+               LOGE("open db(%s) error: %d", path, ret);
+               free(path);
+               return NULL;
+       }
+
+       free(path);
+
+       return db;
+}
+
+void _close_db(sqlite3 *db)
+{
+       sqlite3_close_v2(db);
+}
diff --git a/parser/widget_plugin_parser_internal.h b/parser/widget_plugin_parser_internal.h
new file mode 100644 (file)
index 0000000..8f274de
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __WIDGET_PLUGIN_PARSER_INTERNAL_H__
+#define __WIDGET_PLUGIN_PARSER_INTERNAL_H__
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include <libxml/tree.h>
+#include <sqlite3.h>
+#include <glib.h>
+
+#ifndef API
+#define API __attribute__ ((visibility("default")))
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "WIDGET_PLUGIN_PARSER"
+#endif
+
+struct support_size {
+       char *preview;
+       bool frame;
+       int width;
+       int height;
+};
+
+struct label {
+       char *label;
+       char *lang;
+};
+
+struct icon {
+       char *icon;
+       char *lang;
+};
+
+struct widget_class {
+       char *classid;
+       int update_period;
+       char *setup_appid;
+       char *appid;
+       GList *support_size;
+       GList *label;
+       GList *icon;
+};
+
+int widget_plugin_parser_init(void);
+int widget_plugin_parser_fini(void);
+GList *widget_plugin_parser_parse_manifest(xmlDocPtr doc);
+
+
+int widget_parser_db_insert_widget_class(const char *pkgid, GList *widget_list);
+int widget_parser_db_remove_widget_class(const char *pkgid);
+
+void _free_widget_class(gpointer data);
+
+sqlite3 *_open_db(uid_t uid, bool readonly);
+void _close_db(sqlite3 *db);
+
+int widget_info_get_widget_class(const char *classid, struct widget_class **wc);
+
+#endif
diff --git a/parser/widget_plugin_parser_pkgmgr_interface.c b/parser/widget_plugin_parser_pkgmgr_interface.c
new file mode 100644 (file)
index 0000000..19ca969
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2015  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <glib.h>
+#include <libxml/tree.h>
+
+#include <dlog.h>
+
+#include "widget_plugin_parser_internal.h"
+
+API int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char *pkgid)
+{
+       return widget_plugin_parser_init();
+}
+
+API int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char *pkgid)
+{
+       GList *result;
+
+       result = widget_plugin_parser_parse_manifest(doc);
+       if (result == NULL) {
+               LOGE("parse failed");
+               return -1;
+       }
+
+       if (widget_parser_db_insert_widget_class(pkgid, result))
+               return -1;
+
+       g_list_free_full(result, _free_widget_class);
+
+       return 0;
+}
+
+API int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char *pkgid)
+{
+       return widget_plugin_parser_fini();
+}
+
+API int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char *pkgid)
+{
+       return widget_plugin_parser_init();
+}
+
+API int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc, const char *pkgid)
+{
+       GList *result;
+
+       result = widget_plugin_parser_parse_manifest(doc);
+       if (result == NULL) {
+               LOGE("parse failed");
+               return -1;
+       }
+
+       if (widget_parser_db_remove_widget_class(pkgid))
+               return -1;
+
+       if (widget_parser_db_insert_widget_class(pkgid, result))
+               return -1;
+
+       g_list_free_full(result, _free_widget_class);
+
+       return 0;
+}
+
+API int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char *pkgid)
+{
+       return widget_plugin_parser_fini();
+}
+
+API int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char *pkgid)
+{
+       return widget_plugin_parser_init();
+}
+
+API int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc, const char *pkgid)
+{
+       return widget_parser_db_remove_widget_class(pkgid);
+}
+
+API int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char *pkgid)
+{
+       return widget_plugin_parser_fini();
+}