summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSangyoon Jang <s89.jang@samsung.com>2015-11-18 13:28:10 +0900
committerSangyoon Jang <s89.jang@samsung.com>2015-12-08 11:34:15 +0900
commit9a237e4ff2720421114fad06f9163ac0341c620d (patch)
treebdb88977a3e421b8c29cbfda912e0f3f894ee3ad
parent6e64d2e5b9c25c71356b6a6d366c0a8213fd299f (diff)
downloadwidget-service-accepted/tizen/tv/20151210.083510.tar.gz
widget-service-accepted/tizen/tv/20151210.083510.tar.bz2
widget-service-accepted/tizen/tv/20151210.083510.zip
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>
-rw-r--r--CMakeLists.txt2
-rw-r--r--packaging/libwidget_service.spec17
-rw-r--r--parser/CMakeLists.txt26
-rw-r--r--parser/widget.sql40
-rw-r--r--parser/widget_plugin_parser.c330
-rw-r--r--parser/widget_plugin_parser_db.c303
-rw-r--r--parser/widget_plugin_parser_internal.c137
-rw-r--r--parser/widget_plugin_parser_internal.h62
-rw-r--r--parser/widget_plugin_parser_pkgmgr_interface.c96
9 files changed, 1012 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af447ea..04d74d5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/packaging/libwidget_service.spec b/packaging/libwidget_service.spec
index 490947a..3088406 100644
--- a/packaging/libwidget_service.spec
+++ b/packaging/libwidget_service.spec
@@ -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
index 0000000..95c5697
--- /dev/null
+++ b/parser/CMakeLists.txt
@@ -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
index 0000000..6984494
--- /dev/null
+++ b/parser/widget.sql
@@ -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
index 0000000..e68c0e4
--- /dev/null
+++ b/parser/widget_plugin_parser.c
@@ -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
index 0000000..4d2c5c0
--- /dev/null
+++ b/parser/widget_plugin_parser_db.c
@@ -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
index 0000000..ddc5239
--- /dev/null
+++ b/parser/widget_plugin_parser_internal.c
@@ -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
index 0000000..8f274de
--- /dev/null
+++ b/parser/widget_plugin_parser_internal.h
@@ -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
index 0000000..19ca969
--- /dev/null
+++ b/parser/widget_plugin_parser_pkgmgr_interface.c
@@ -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();
+}