summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaehyeon Jung <darrenh.jung@samsung.com>2015-11-17 15:04:00 +0900
committerDaehyeon Jung <darrenh.jung@samsung.com>2016-01-12 10:12:53 +0900
commitf1ba1e25bae135579f049fe179432ca287715796 (patch)
tree53d3e088eca1f7819a1281820bd5ddc07acfa3c5
parent9daa42ec89b6408d1166928d034bdb102bc27ecf (diff)
downloadwidget-service-submit/tizen/20160112.015033.tar.gz
widget-service-submit/tizen/20160112.015033.tar.bz2
widget-service-submit/tizen/20160112.015033.zip
- Support pepper-based widget framework Change-Id: Id9ea8dcd4a0b574f39762601bf5db2b94fcd9dfb Signed-off-by: Daehyeon Jung <darrenh.jung@samsung.com>
-rw-r--r--CMakeLists.txt5
-rw-r--r--include/debug.h12
-rw-r--r--include/widget_instance.h73
-rw-r--r--packaging/libwidget_service.spec8
-rw-r--r--src/widget_instance.c849
5 files changed, 939 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9224ef6..188957a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,6 @@ pkg_check_modules(pkgs REQUIRED
dlog
glib-2.0
gio-2.0
- com-core
sqlite3
db-util
pkgmgr-info
@@ -24,8 +23,8 @@ pkg_check_modules(pkgs REQUIRED
icu-uc
bundle
capi-base-common
- libdrm
capi-system-info
+ aul
)
FOREACH(flag ${pkgs_CFLAGS})
@@ -49,6 +48,7 @@ ADD_DEFINITIONS("-DDEFAULT_MASTER_CONF=\"/usr/share/widget-service/conf.ini\"")
SET(BUILD_SOURCE
src/widget_service.c
src/widget_conf.c
+ src/widget_instance.c
)
ADD_LIBRARY(${PROJECT_NAME} SHARED ${BUILD_SOURCE})
@@ -67,6 +67,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_service.h DESTINATION i
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_service_internal.h DESTINATION include/${PROJECT_NAME})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_errno.h DESTINATION include/${PROJECT_NAME})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_conf.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_instance.h DESTINATION include/${PROJECT_NAME})
ADD_SUBDIRECTORY(parser)
diff --git a/include/debug.h b/include/debug.h
index ed02a48..c1cfa3d 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -35,5 +35,17 @@ extern FILE *__file_log_fp;
#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [%s/%s:%d] " format, widget_util_basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
#endif
+#ifndef _E
+#define _E LOGE
+#endif
+
+#ifndef _D
+#define _D LOGD
+#endif
+
+#ifndef _I
+#define _I LOGI
+#endif
+
#define EAPI __attribute__((visibility("default")))
/* End of a file */
diff --git a/include/widget_instance.h b/include/widget_instance.h
new file mode 100644
index 0000000..24ae27c
--- /dev/null
+++ b/include/widget_instance.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef __WIDGET_INSTANCE_H__
+#define __WIDGET_INSTANCE_H__
+
+#include <bundle.h>
+#include <aul.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WIDGET_K_ID AUL_K_APPID
+#define WIDGET_K_CLASS "__WIDGET_CLASS__"
+#define WIDGET_K_INSTANCE "__WIDGET_INSTANCE__"
+#define WIDGET_K_STATUS "__WIDGET_STATUS__"
+#define WIDGET_K_ENDPOINT "__WIDGET_ENDPOINT__"
+
+#define WIDGET_K_CALLER "__WIDGET_CALLER_PID__"
+#define WIDGET_K_OPERATION "__WIDGET_OP__"
+#define WIDGET_K_WIDTH "__WIDGET_WIDTH__"
+#define WIDGET_K_HEIGHT "__WIDGET_HEIGHT__"
+#define WIDGET_K_REASON "__WIDGET_REASON__"
+
+typedef enum widget_instance_event {
+ WIDGET_INSTANCE_EVENT_CREATE = 0,
+ WIDGET_INSTANCE_EVENT_DESTROY = 1,
+ WIDGET_INSTANCE_EVENT_TERMINATE = 2,
+ WIDGET_INSTANCE_EVENT_PAUSE = 3,
+ WIDGET_INSTANCE_EVENT_RESUME = 4,
+ WIDGET_INSTANCE_EVENT_UPDATE = 5,
+ WIDGET_INSTANCE_EVENT_PERIOD_CHANGED = 6,
+ WIDGET_INSTANCE_EVENT_SIZE_CHANGED = 7,
+ WIDGET_INSTANCE_EVENT_MAX,
+} widget_instance_event_e;
+
+typedef struct _widget_instance* widget_instance_h;
+typedef int (*widget_instance_foreach_cb)(widget_instance_h instance, void *data);
+int widget_instance_foreach(const char *widget_id, widget_instance_foreach_cb cb, void *data);
+
+int widget_instance_get_id(widget_instance_h instance, char **id);
+int widget_instance_get_content(widget_instance_h instance, bundle **content);
+int widget_instance_get_width(widget_instance_h instance, int *w);
+int widget_instance_get_height(widget_instance_h instance, int *h);
+int widget_instance_get_period(widget_instance_h instance, double *period);
+
+int widget_instance_create(const char *widget_id, char **instance_id);
+int widget_instance_launch(const char *widget_id, const char *instance_id, bundle *content_info, int w, int h);
+int widget_instance_terminate(const char *widget_id, const char *instance_id);
+int widget_instance_destroy(const char *widget_id, const char *instance_id);
+int widget_instance_init(const char *viewer_id);
+int widget_instance_fini();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/packaging/libwidget_service.spec b/packaging/libwidget_service.spec
index 7ca9091..60ef8f6 100644
--- a/packaging/libwidget_service.spec
+++ b/packaging/libwidget_service.spec
@@ -1,5 +1,3 @@
-%bcond_with wayland
-
Name: libwidget_service
Summary: Service API for gathering installed widget information
Version: 1.2.0
@@ -23,6 +21,7 @@ BuildRequires: pkgconfig(capi-base-common)
BuildRequires: pkgconfig(capi-system-info)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(aul)
%if "%{model_build_feature_widget}" == "0"
ExclusiveArch:
@@ -80,10 +79,7 @@ chsmack -a "User::Home" %{_sysconfdir}/skel/.applications/dbspace/.widget.db
%files devel
%manifest %{name}.manifest
%defattr(-,root,root,-)
-%{_includedir}/widget_service/widget_service.h
-%{_includedir}/widget_service/widget_service_internal.h
-%{_includedir}/widget_service/widget_errno.h
-%{_includedir}/widget_service/widget_conf.h
+%{_includedir}/widget_service/*
%{_libdir}/pkgconfig/widget_service.pc
# End of a file
diff --git a/src/widget_instance.c b/src/widget_instance.c
new file mode 100644
index 0000000..ba1d8fc
--- /dev/null
+++ b/src/widget_instance.c
@@ -0,0 +1,849 @@
+/*
+ * 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 "widget_instance.h"
+#include <dlog.h>
+#include "debug.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <sqlite3.h>
+#include <tzplatform_config.h>
+#include <aul.h>
+#include <aul_app_com.h>
+#include <widget_service.h>
+
+#define USER_UID_MIN 5000
+#define MAX_INSTANCE_ID_LEN 256
+#define WIDGET_CLASS_DELIMITER "@"
+#define QUERY_MAX_LEN 8192
+
+enum {
+ WIDGET_INSTANCE_CREATED,
+ WIDGET_INSTANCE_RUNNING,
+ WIDGET_INSTANCE_TERMINATED,
+ WIDGET_INSTANCE_DELETED
+};
+
+struct _widget_instance {
+ char *id;
+ pid_t pid;
+ char *widget_id;
+ int w;
+ int h;
+ double period;
+ bundle *content_info;
+ int status;
+ int stored;
+};
+
+struct widget_app {
+ char *viewer_id;
+ char *widget_id;
+ int cnt;
+ GList *instances;
+};
+
+static char *wayland_display = NULL;
+static char *xdg_runtime_dir = NULL;
+
+static GList *_widget_instances = NULL;
+static GList *_widget_apps = NULL;
+
+static sqlite3 *_widget_db = NULL;
+static char *viewer_appid = NULL;
+static aul_app_com_connection_h conn = NULL;
+
+#define QUERY_CREATE_TABLE_WIDGET "create table if not exists widget_instance" \
+ "(widget_id text, " \
+ "viewer_id text, " \
+ "content_info text, " \
+ "instance_id text, " \
+ "PRIMARY KEY(instance_id)) "
+
+static const char *__get_widget_db(uid_t uid)
+{
+ const char *widget_db = NULL;
+
+ if (uid >= USER_UID_MIN) {
+ tzplatform_set_user(uid);
+ widget_db = tzplatform_mkpath(TZ_USER_DB, ".widget_instance.db");
+ tzplatform_reset_user();
+ } else {
+ _E("Fail to get widget db. only regular user has widget db");
+ return NULL;
+ }
+
+ _E("%s", widget_db);
+
+ return widget_db;
+}
+
+static int __init(bool readonly)
+{
+ int rc;
+
+ uid_t uid = getuid();
+
+ if (_widget_db) {
+ _D("already initialized");
+ return 0;
+ }
+
+ rc = sqlite3_open_v2(__get_widget_db(uid), &_widget_db,
+ readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+ if (SQLITE_OK != rc) {
+ _E("Can't open database: %d, %s, extended: %d", rc, sqlite3_errmsg(_widget_db),
+ sqlite3_extended_errcode(_widget_db));
+ goto err;
+ }
+
+ rc = sqlite3_exec(_widget_db, "PRAGMA journal_mode = PERSIST", NULL, NULL, NULL);
+ if (SQLITE_OK != rc) {
+ _E("Fail to change journal mode\n");
+ goto err;
+ }
+
+ rc = sqlite3_exec(_widget_db, QUERY_CREATE_TABLE_WIDGET, NULL, NULL, NULL);
+ if (SQLITE_OK != rc) {
+ _E("Fail to create tables\n");
+ goto err;
+ }
+
+ return 0;
+err:
+ if (_widget_db) {
+ sqlite3_close(_widget_db);
+ _widget_db = NULL;
+ }
+
+ return -1;
+}
+
+static int __fini(void)
+{
+ if (_widget_db) {
+ sqlite3_close(_widget_db);
+ _widget_db = NULL;
+ }
+
+ return 0;
+}
+
+static struct _widget_instance *__pick_instance(const char *widget_id, const char *instance_id)
+{
+ GList *apps = _widget_apps;
+ GList *instances = NULL;
+ struct widget_app *app = NULL;
+ struct _widget_instance *instance = NULL;
+
+ while (apps) {
+ app = apps->data;
+ if (app && g_strcmp0(widget_id, app->widget_id) == 0) {
+ instances = app->instances;
+ while (instances) {
+ instance = instances->data;
+ if (instance && g_strcmp0(instance_id, instance->id) == 0) {
+ return instance;
+ }
+ instances = instances->next;
+ }
+ }
+ apps = apps->next;
+ }
+
+ return NULL;
+}
+
+static struct widget_app *__pick_app(const char *widget_id)
+{
+ GList *apps = _widget_apps;
+ struct widget_app *app = NULL;
+
+ while (apps) {
+ app = apps->data;
+ if (app && app->widget_id && g_strcmp0(widget_id, app->widget_id) == 0)
+ return app;
+
+ apps = apps->next;
+ }
+
+ return NULL;
+}
+
+static struct widget_app *__add_app(const char *widget_id, const char *viewer_id)
+{
+ struct widget_app *app = NULL;
+
+ app = (struct widget_app *)malloc(sizeof(struct widget_app));
+ if (app == NULL) {
+ _E("out of memory");
+ return NULL;
+ }
+
+ app->viewer_id = g_strdup(viewer_id);
+ app->widget_id = g_strdup(widget_id);
+ app->instances = NULL;
+ app->cnt = 0;
+
+ _widget_apps = g_list_append(_widget_apps, app);
+
+ return app;
+}
+
+static const char *__create_instance_id(const char *widget_id)
+{
+ char instance_id[MAX_INSTANCE_ID_LEN];
+ int id = 0;
+ struct widget_app *app = NULL;
+
+ if (widget_id == NULL)
+ return NULL;
+
+ app = __pick_app(widget_id);
+
+ if (app == NULL) {
+ app = __add_app(widget_id, viewer_appid);
+ if (app == NULL)
+ return NULL;
+ }
+
+ id = app->cnt;
+ app->cnt++;
+
+ snprintf(instance_id, MAX_INSTANCE_ID_LEN, "%d:%s", id, widget_id);
+
+ _D("new instance: %s", instance_id);
+
+ return g_strdup(instance_id);
+}
+
+static struct _widget_instance *__add_instance(const char *id, const char *widget_id)
+{
+ struct _widget_instance *instance = NULL;
+ struct widget_app *app = NULL;
+
+ instance = (struct _widget_instance *)malloc(sizeof(struct _widget_instance));
+ if (instance == NULL) {
+ _E("out of memory");
+ return NULL;
+ }
+
+ instance->status = WIDGET_INSTANCE_CREATED;
+ instance->id = (char *)id;
+ instance->pid = 0;
+ instance->stored = 0;
+ instance->widget_id = g_strdup(widget_id);
+ instance->content_info = NULL;
+
+ _widget_instances = g_list_append(_widget_instances, instance);
+
+ app = __pick_app(widget_id);
+ if (app)
+ app->instances = g_list_append(app->instances, instance);
+ else
+ _E("failed to find app: %s", widget_id);
+
+ return instance;
+}
+
+static void __remove_instance(struct _widget_instance *instance)
+{
+ struct widget_app *app = NULL;
+
+ if (instance == NULL) {
+ _E("invalid argument");
+ return;
+ }
+
+ if (instance->widget_id)
+ app = __pick_app(instance->widget_id);
+
+ if (app) {
+ app->instances = g_list_remove(app->instances, instance);
+ if (app->instances == NULL) {
+ _widget_apps = g_list_remove(_widget_apps, app);
+ free(app);
+ app = NULL;
+ }
+ }
+
+ _widget_instances = g_list_remove(_widget_instances, instance);
+
+ if (instance->widget_id) {
+ free(instance->widget_id);
+ instance->widget_id = NULL;
+ }
+
+ if (instance->id) {
+ free(instance->id);
+ instance->id = NULL;
+ }
+
+ if (instance->content_info) {
+ bundle_free(instance->content_info);
+ instance->content_info = NULL;
+ }
+
+ free(instance);
+}
+
+static int __load_instance_list()
+{
+ int rc;
+ char select_query[] = "SELECT widget_id, content_info, instance_id FROM widget_instance WHERE viewer_id=?";
+ char *widget_id;
+ char *content_info;
+ char *instance_id;
+ struct _widget_instance *instance = NULL;
+ struct widget_app *app = NULL;
+
+ sqlite3_stmt* p_statement;
+
+ if (_widget_db == NULL) {
+ _E("widget db is not initialized");
+ return -1;
+ }
+
+ rc = sqlite3_prepare_v2(_widget_db, select_query, strlen(select_query),
+ &p_statement, NULL);
+
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> executing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ return -1;
+ }
+
+ sqlite3_bind_text(p_statement, 1, viewer_appid, -1, SQLITE_TRANSIENT);
+
+ while (sqlite3_step(p_statement) == SQLITE_ROW) {
+ widget_id = (char *)sqlite3_column_text(p_statement, 0);
+ content_info = (char *)sqlite3_column_text(p_statement, 1);
+ instance_id = (char *)sqlite3_column_text(p_statement, 2);
+
+ app = __pick_app(widget_id);
+ if (app == NULL) {
+ app = __add_app(widget_id, viewer_appid);
+ if (app == NULL) {
+ _E("failed to add app: %s", widget_id);
+ continue;
+ }
+ /* TODO set app->cnt to last instance number, or need to replace how to create id */
+ }
+
+ instance = __add_instance(instance_id, widget_id);
+ if (instance == NULL) {
+ _E("failed to add instance: %s", instance_id);
+ continue;
+ }
+
+ instance->content_info = bundle_decode((const bundle_raw *)content_info, strlen(content_info));
+ if (instance->content_info == NULL)
+ _E("failed to decode bundle: %s", instance_id);
+ instance->status = WIDGET_INSTANCE_CREATED;
+ instance->stored = 1;
+ }
+
+ rc = sqlite3_finalize(p_statement);
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> finalizing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ }
+
+ return 0;
+}
+
+static int __update_instance_info(struct _widget_instance *instance)
+{
+ int rc = 0;
+ const char insert_query[] = "INSERT INTO widget_instance(widget_id, viewer_id, content_info, instance_id) VALUES(?,?,?,?)";
+ const char update_query[] = "UPDATE widget_instance SET content_info=? WHERE instance_id=?";
+ const char delete_query[] = "DELETE FROM widget_instance WHERE instance_id=?";
+ sqlite3_stmt* p_statement;
+ struct widget_app *app = NULL;
+ char *content = NULL;
+ int content_len = 0;
+
+ if (_widget_db == NULL) {
+ _E("call widget_instance_init() first");
+ return -1;
+ }
+
+ if (instance == NULL) {
+ _E("wrong argument");
+ return -1;
+ }
+
+ if (instance->content_info) {
+ rc = bundle_encode(instance->content_info, (bundle_raw **)&content, &content_len);
+ if (rc != BUNDLE_ERROR_NONE)
+ _E("failed to get bundle data: %s", instance->id);
+ }
+
+ if (content == NULL) {
+ content = g_strdup("NULL");
+ content_len = strlen("NULL");
+ }
+
+ if (instance->stored) {
+ if (instance->status == WIDGET_INSTANCE_DELETED) {
+ rc = sqlite3_prepare_v2(_widget_db, delete_query, strlen(delete_query),
+ &p_statement, NULL);
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> executing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ goto cleanup;
+ }
+
+ sqlite3_bind_text(p_statement, 1, instance->id, -1, SQLITE_TRANSIENT);
+ } else {
+ rc = sqlite3_prepare_v2(_widget_db, update_query, strlen(update_query),
+ &p_statement, NULL);
+
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> executing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ goto cleanup;
+ }
+
+ sqlite3_bind_text(p_statement, 1, content, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(p_statement, 2, instance->id, -1, SQLITE_TRANSIENT);
+ }
+ } else {
+ app = __pick_app(instance->widget_id);
+ if (app == NULL) {
+ _E("can not find app: %s", instance->id);
+ goto cleanup;
+ }
+
+ rc = sqlite3_prepare_v2(_widget_db, insert_query, strlen(insert_query),
+ &p_statement, NULL);
+
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> executing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ goto cleanup;
+ }
+
+ sqlite3_bind_text(p_statement, 1, instance->widget_id, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(p_statement, 2, app->viewer_id, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(p_statement, 3, content, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(p_statement, 4, instance->id, -1, SQLITE_TRANSIENT);
+ }
+
+ rc = sqlite3_step(p_statement);
+
+ if (rc == SQLITE_DONE) {
+ if (instance->status == WIDGET_INSTANCE_DELETED) {
+ __remove_instance(instance);
+ instance = NULL;
+ } else
+ instance->stored = 1;
+ }
+
+ if (rc != SQLITE_DONE) {
+ _E("Sqlite3 error [%d] : <%s> executing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ }
+
+cleanup:
+
+ if (p_statement) {
+ rc = sqlite3_finalize(p_statement);
+ if (rc != SQLITE_OK) {
+ _E("Sqlite3 error [%d] : <%s> finalizing statement\n", rc,
+ sqlite3_errmsg(_widget_db));
+ }
+ }
+
+ if (content) {
+ free(content);
+ content = NULL;
+ }
+
+ return rc;
+}
+
+EAPI int widget_instance_create(const char *widget_id, char **instance_id)
+{
+ const char *id = NULL;
+ struct _widget_instance *instance = NULL;
+
+ _D("create: %s", widget_id);
+
+ id = __create_instance_id(widget_id);
+ if (!id) {
+ _E("failed to get instance id for %s", widget_id);
+ return -1;
+ }
+
+ instance = __add_instance(id, widget_id);
+
+ if (instance) {
+ *instance_id = (char *)id;
+ _D("create done");
+ return 0;
+ }
+
+ *instance_id = NULL;
+
+ return -1;
+}
+
+static int __send_aul_cmd(const char *widget_id, const char *instance_id, bundle *extra)
+{
+ int ret = 0;
+ const char *appid;
+ const char *classid = widget_id;
+ bundle *b = extra;
+
+ appid = g_strstr_len(widget_id, strlen(widget_id), WIDGET_CLASS_DELIMITER) + 1;
+ if (appid != (const char *)1) { /* move pointer next to delimiter */
+ if (appid > widget_id + (sizeof(char) * strlen(widget_id)))
+ return -1; /* bad ptr */
+ } else {
+ appid = widget_id;
+ }
+
+ if (b == NULL) {
+ b = bundle_create();
+ }
+
+ bundle_add_str(b, WIDGET_K_INSTANCE, instance_id);
+
+ bundle_add_str(b, WIDGET_K_CLASS, classid);
+
+ ret = aul_launch_app(appid, b);
+
+ if (!extra) {
+ bundle_free(b);
+ b = NULL;
+ }
+
+ return ret;
+}
+
+static int __set_width(bundle *content_info, int w)
+{
+ char wbuf[6];
+ if (content_info == NULL || w < 0)
+ return -1;
+
+ snprintf(wbuf, 6, "%d", w);
+ bundle_add_str(content_info, WIDGET_K_WIDTH, wbuf);
+
+ return 0;
+}
+
+static int __set_height(bundle *content_info, int h)
+{
+ char hbuf[6];
+ if (content_info == NULL || h < 0)
+ return -1;
+
+ snprintf(hbuf, 6, "%d", h);
+ bundle_add_str(content_info, WIDGET_K_HEIGHT, hbuf);
+
+ return 0;
+}
+
+EAPI int widget_instance_launch(const char *widget_id, const char *instance_id, bundle *content_info, int w, int h)
+{
+ int ret = 0;
+ char pid_buf[6];
+ bundle *b = content_info;
+ char *instance = (char *)instance_id;
+
+ _D("launch: %s %s", widget_id, instance_id);
+
+ if (widget_id == NULL) {
+ _E("wrong arguments");
+ return -1;
+ }
+
+ if (xdg_runtime_dir == NULL) {
+ xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
+ if (xdg_runtime_dir == NULL) {
+ _E("failed to get XDG_RUNTIME_DIR");
+ return -1;
+ }
+ }
+
+ if (wayland_display == NULL) {
+ wayland_display = getenv("WAYLAND_DISPLAY");
+ if (wayland_display == NULL) {
+ _E("unable to get wayland display port");
+ return -1;
+ }
+ }
+
+ if (instance == NULL) {
+ ret = widget_instance_create(widget_id, &instance);
+ if (ret < 0 || instance == NULL) {
+ _E("failed to create instance for %s", widget_id);
+ return -1;
+ }
+ }
+
+ if (b == NULL) {
+ b = bundle_create();
+ if (b == NULL) {
+ _E("out of memory");
+ return -1;
+ }
+ }
+
+ snprintf(pid_buf, sizeof(pid_buf), "%d", getpid());
+ bundle_add_str(b, WIDGET_K_CALLER, pid_buf);
+ bundle_add_str(b, AUL_K_WAYLAND_DISPLAY, wayland_display);
+ bundle_add_str(b, AUL_K_WAYLAND_WORKING_DIR, xdg_runtime_dir);
+ bundle_add_str(b, WIDGET_K_OPERATION, "create");
+
+ __set_width(b, w);
+ __set_height(b, h);
+
+ ret = __send_aul_cmd(widget_id, instance, b);
+
+ if (ret) {
+ struct _widget_instance *i = __pick_instance(widget_id, instance);
+ if (i)
+ i->pid = ret;
+ }
+
+ if (content_info == NULL)
+ bundle_free(b);
+
+ return ret;
+}
+
+EAPI int widget_instance_terminate(const char *widget_id, const char *instance_id)
+{
+ int ret = 0;
+ bundle *b = bundle_create();
+
+ if (widget_id == NULL || instance_id == NULL || b == NULL)
+ return -1;
+
+ bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
+
+ ret = __send_aul_cmd(widget_id, instance_id, b);
+
+ bundle_free(b);
+
+ return ret;
+}
+
+EAPI int widget_instance_destroy(const char *widget_id, const char *instance_id)
+{
+ int ret = 0;
+ bundle *b = bundle_create();
+
+ if (widget_id == NULL || instance_id == NULL || b == NULL)
+ return -1;
+
+ bundle_add_str(b, WIDGET_K_OPERATION, "destroy");
+
+ ret = __send_aul_cmd(widget_id, instance_id, b);
+
+ bundle_free(b);
+
+ return ret;
+}
+
+EAPI int widget_instance_foreach(const char *widget_id, widget_instance_foreach_cb cb, void *data)
+{
+ GList *apps = _widget_apps;
+ GList *instances = NULL;
+ struct widget_app *app = NULL;
+ struct _widget_instance *instance = NULL;
+
+ if (widget_id == NULL || cb == NULL)
+ return -1;
+
+ while (apps) {
+ app = apps->data;
+ if (app && g_strcmp0(app->widget_id, widget_id) == 0) {
+ instances = app->instances;
+ while (instances) {
+ instance = instances->data;
+ if (instance && cb(instance, data) < 0) {
+ break;
+ }
+ instances = instances->next;
+ }
+ }
+ apps = apps->next;
+ }
+
+ return 0;
+}
+
+
+static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundle *envelope, void *user_data)
+{
+ char *widget_id = NULL;
+ char *instance_id = NULL;
+ int *status = NULL;
+ size_t status_sz = 0;
+ int cmd = 0;
+ struct _widget_instance *instance;
+
+ bundle_get_str(envelope, WIDGET_K_CLASS, &widget_id);
+ bundle_get_str(envelope, WIDGET_K_INSTANCE, &instance_id);
+ bundle_get_byte(envelope, WIDGET_K_STATUS, (void **)&status, &status_sz);
+
+ if (widget_id == NULL || instance_id == NULL || status == NULL) {
+ _E("undefined class or instance %s of %s", instance_id, widget_id);
+ if (status != NULL) {
+ _E("cmd: %d", *status);
+ }
+ return 0;
+ }
+
+ instance = __pick_instance(widget_id, instance_id);
+
+ if (instance == NULL) {
+ _E("undefined instance id: %s of %s", instance_id, widget_id);
+ return 0;
+ }
+
+ cmd = *status;
+
+ switch (cmd) {
+ case WIDGET_INSTANCE_EVENT_CREATE:
+ if (instance->content_info)
+ bundle_free(instance->content_info);
+
+ instance->content_info = bundle_dup(envelope);
+ __update_instance_info(instance);
+ break;
+ case WIDGET_INSTANCE_EVENT_TERMINATE:
+ if (instance->content_info)
+ bundle_free(instance->content_info);
+
+ instance->content_info = bundle_dup(envelope);
+ instance->status = WIDGET_INSTANCE_TERMINATED;
+ __update_instance_info(instance);
+ break;
+ case WIDGET_INSTANCE_EVENT_DESTROY:
+ instance->status = WIDGET_INSTANCE_DELETED;
+ __update_instance_info(instance);
+ break;
+ case WIDGET_INSTANCE_EVENT_PAUSE:
+ break;
+ case WIDGET_INSTANCE_EVENT_RESUME:
+ instance->status = WIDGET_INSTANCE_RUNNING;
+ break;
+ case WIDGET_INSTANCE_EVENT_UPDATE:
+ if (instance->content_info)
+ bundle_free(instance->content_info);
+
+ instance->content_info = bundle_dup(envelope);
+ __update_instance_info(instance);
+ break;
+ default:
+ _E("unknown command: %d", cmd);
+ break;
+ }
+
+ return 0;
+}
+
+EAPI int widget_instance_init(const char *viewer_id)
+{
+ if (viewer_id == NULL)
+ return -1;
+
+ viewer_appid = g_strdup(viewer_id);
+ __init(false);
+
+ __load_instance_list();
+
+ if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn) < 0) {
+ _E("failed to create app com endpoint");
+ return -1;
+ }
+
+ return 0;
+}
+
+EAPI int widget_instance_fini()
+{
+
+ if (conn) {
+ if (aul_app_com_leave(conn) < 0)
+ _E("failed to leave app com endpoint");
+ }
+
+ __fini();
+
+ if (viewer_appid) {
+ g_free(viewer_appid);
+ viewer_appid = NULL;
+ }
+
+ return 0;
+}
+
+EAPI int widget_instance_get_id(widget_instance_h instance, char **id)
+{
+ if (instance == NULL || id == NULL)
+ return -1;
+
+ *id = (char *)instance->id;
+ return 0;
+}
+
+EAPI int widget_instance_get_content(widget_instance_h instance, bundle **content)
+{
+ if (instance == NULL || content == NULL)
+ return -1;
+
+ *content = instance->content_info;
+ return 0;
+}
+
+EAPI int widget_instance_get_width(widget_instance_h instance, int *w)
+{
+ if (instance == NULL || w == NULL)
+ return -1;
+
+ *w = instance->w;
+ return 0;
+}
+
+EAPI int widget_instance_get_height(widget_instance_h instance, int *h)
+{
+ if (instance == NULL || h == NULL)
+ return -1;
+
+ *h = instance->h;
+ return 0;
+}
+
+EAPI int widget_instance_get_period(widget_instance_h instance, double *period)
+{
+ if (instance == NULL || period == NULL)
+ return -1;
+
+ *period = instance->period;
+ return 0;
+}