diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | include/debug.h | 12 | ||||
-rw-r--r-- | include/widget_instance.h | 73 | ||||
-rw-r--r-- | packaging/libwidget_service.spec | 8 | ||||
-rw-r--r-- | src/widget_instance.c | 849 |
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] [[32m%s/%s[0m:%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; +} |