From a0245b791d94a5a9453ae095f48cd18f195ee282 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Thu, 10 Mar 2016 14:53:13 +0900 Subject: [PATCH 01/16] change db location Change-Id: Ica77c0a7400bca4d6825b6ac42343f076bee68ac --- CMakeLists.txt | 1 + packaging/libwidget_service.spec | 1 + src/widget_instance.c | 38 ++++++++++++++++---------------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 362ebba..d4171db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ pkg_check_modules(pkgs REQUIRED bundle capi-base-common capi-system-info + capi-appfw-app-common aul libtzplatform-config uuid diff --git a/packaging/libwidget_service.spec b/packaging/libwidget_service.spec index ec44ca1..788c158 100644 --- a/packaging/libwidget_service.spec +++ b/packaging/libwidget_service.spec @@ -18,6 +18,7 @@ BuildRequires: pkgconfig(uuid) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(icu-uc) BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-appfw-app-common) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(libtzplatform-config) diff --git a/src/widget_instance.c b/src/widget_instance.c index 88f345f..c11eea3 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -27,17 +27,21 @@ #include #include #include -#include #include #include #include #include +#include #define USER_UID_MIN 5000 #define MAX_INSTANCE_ID_LEN 256 #define WIDGET_CLASS_DELIMITER "@" #define QUERY_MAX_LEN 8192 +#ifndef TIZEN_PATH_MAX +#define TIZEN_PATH_MAX 1024 +#endif + enum { WIDGET_INSTANCE_CREATED, WIDGET_INSTANCE_RUNNING, @@ -81,36 +85,26 @@ static aul_app_com_connection_h conn = NULL; "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(); + char db_path[TIZEN_PATH_MAX]; + char *app_path = NULL; if (_widget_db) { _D("already initialized"); return 0; } - rc = sqlite3_open_v2(__get_widget_db(uid), &_widget_db, + app_path = app_get_data_path(); + if (!app_path) { + _D("failed to get app path"); + return 0; + } + + snprintf(db_path, sizeof(db_path), "%s/%s", app_path, ".widget_instance.db"); + + rc = sqlite3_open_v2(db_path, &_widget_db, readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (rc != SQLITE_OK) { _E("Can't open database: %d, %s, extended: %d", rc, sqlite3_errmsg(_widget_db), -- 2.7.4 From 8ce4d428e0ed3ae0f8c5bdba99b82307d22dc2ab Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Wed, 2 Mar 2016 20:05:35 +0900 Subject: [PATCH 02/16] implement empty functions Change-Id: I034f1857b869895788726a198dd75014582891e9 Signed-off-by: Daehyeon Jung --- CMakeLists.txt | 4 + include/widget_instance.h | 8 ++ packaging/libwidget_service.spec | 1 + src/widget_instance.c | 88 +++++++++++++++++- src/widget_service.c | 195 ++++++++++++++++++++++++++++++++++++--- tool/widget_test.c | 61 ++++++++++++ 6 files changed, 337 insertions(+), 20 deletions(-) create mode 100644 tool/widget_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d4171db..7ff419b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,10 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_I CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc") +ADD_EXECUTABLE(widget_test tool/widget_test.c) +TARGET_LINK_LIBRARIES(widget_test ${pkgs_LDFLAGS} ${pkg_extra_LDFLAGS} widget_service) +INSTALL(TARGETS widget_test DESTINATION bin) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/widget_service.h DESTINATION include/${PROJECT_NAME}) 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}) diff --git a/include/widget_instance.h b/include/widget_instance.h index 24ae27c..ef885e1 100644 --- a/include/widget_instance.h +++ b/include/widget_instance.h @@ -65,6 +65,14 @@ int widget_instance_destroy(const char *widget_id, const char *instance_id); int widget_instance_init(const char *viewer_id); int widget_instance_fini(); +widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id); +int widget_instance_get_instance_list(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, void *data), void *data); +void widget_instance_unref(widget_instance_h instance); +widget_instance_h widget_instance_ref(widget_instance_h instance); +int widget_instance_change_period(widget_instance_h instance, double period); +int widget_instance_trigger_update(widget_instance_h instance, bundle *b, int force); +int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, int status, const char *instance_id, void *data), void *data); + #ifdef __cplusplus } #endif diff --git a/packaging/libwidget_service.spec b/packaging/libwidget_service.spec index 788c158..aaf5bf5 100644 --- a/packaging/libwidget_service.spec +++ b/packaging/libwidget_service.spec @@ -77,6 +77,7 @@ chsmack -a "User::Home" %{_sysconfdir}/skel/.applications/dbspace/.widget.db %{_sysconfdir}/package-manager/parserlib/libwidget-application.so %{_sysconfdir}/skel/.applications/dbspace/.widget.db %{TZ_SYS_DB}/.widget.db +%{_bindir}/widget_test %files devel %manifest %{name}.manifest diff --git a/src/widget_instance.c b/src/widget_instance.c index c11eea3..0580411 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -59,6 +59,7 @@ struct _widget_instance { bundle *content_info; int status; int stored; + int ref; }; struct widget_app { @@ -77,6 +78,7 @@ 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, " \ @@ -248,6 +250,7 @@ static struct _widget_instance *__add_instance(const char *id, const char *widge instance->stored = 0; instance->widget_id = g_strdup(widget_id); instance->content_info = NULL; + instance->ref = 0; _widget_instances = g_list_append(_widget_instances, instance); @@ -446,10 +449,9 @@ static int __update_instance_info(struct _widget_instance *instance) rc = sqlite3_step(p_statement); if (rc == SQLITE_DONE) { - if (instance->status == WIDGET_INSTANCE_DELETED) { - __remove_instance(instance); - instance = NULL; - } else + if (instance->status == WIDGET_INSTANCE_DELETED) + widget_instance_unref(instance); + else instance->stored = 1; } @@ -690,7 +692,6 @@ EAPI int widget_instance_foreach(const char *widget_id, widget_instance_foreach_ 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; @@ -841,3 +842,80 @@ EAPI int widget_instance_get_period(widget_instance_h instance, double *period) *period = instance->period; return 0; } + +EAPI int widget_instance_change_period(widget_instance_h instance, double period) +{ + return 0; +} + +EAPI int widget_instance_trigger_update(widget_instance_h instance, bundle *b, int force) +{ + return 0; +} + +EAPI widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id) +{ + widget_instance_h instance; + + if (widget_id == NULL || instance_id == NULL) + return NULL; + + if (_widget_apps && _widget_instances) { + instance = __pick_instance(widget_id, instance_id); + return widget_instance_ref(instance); + } + + return NULL; +} + +EAPI int widget_instance_get_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data) +{ + widget_instance_h instance; + struct widget_app *app; + GList *head = NULL; + + if (widget_id == NULL) + return -1; + + if (_widget_apps) + app = __pick_app(widget_id); + else + return -2; + + if (app) { + head = app->instances; + + while (head) { + instance = (widget_instance_h)head->data; + if (cb(instance->widget_id, instance->id, data) != 0) + break; + + head = head->next; + } + } + + return 0; +} + +EAPI void widget_instance_unref(widget_instance_h instance) +{ + if (instance == NULL) + return; + + instance->ref--; + + if (instance->ref > -1) + return; + + __remove_instance(instance); +} + +EAPI widget_instance_h widget_instance_ref(widget_instance_h instance) +{ + if (instance) + instance->ref++; + + return instance; +} + + diff --git a/src/widget_service.c b/src/widget_service.c index 344363d..91bb143 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -30,6 +30,7 @@ #include "widget_errno.h" #include "debug.h" #include "widget_conf.h" +#include "widget_instance.h" #include "widget_service.h" static inline bool _is_widget_feature_enabled(void) @@ -261,14 +262,59 @@ static int _get_widget_supported_sizes(const char *widget_id, int *cnt, EAPI int widget_service_change_period(const char *pkgname, const char *id, double period) { - _E("not supported"); - return WIDGET_ERROR_NOT_SUPPORTED; + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (!pkgname || !id || period < 0.0f) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + widget_instance_h instance; + int ret; + + instance = widget_instance_get_instance(pkgname, id); + + if (!instance) { + _E("instance not exists or out of bound(package)"); + return WIDGET_ERROR_PERMISSION_DENIED; + } + + ret = widget_instance_change_period(instance, period); + + widget_instance_unref(instance); + + return ret; } EAPI int widget_service_trigger_update(const char *widget_id, const char *id, bundle *b, int force) { - _E("not supported"); - return WIDGET_ERROR_NOT_SUPPORTED; + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (!widget_id || !id || !b) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + widget_instance_h instance; + int ret; + + instance = widget_instance_get_instance(widget_id, id); + if (!instance) { + _E("instance not exists or out of bound(package)"); + return WIDGET_ERROR_PERMISSION_DENIED; + } + + ret = widget_instance_trigger_update(instance, b, force); + + widget_instance_unref(instance); + + return ret; } EAPI int widget_service_get_widget_list(widget_list_cb cb, void *data) @@ -626,26 +672,60 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) } set_last_result(WIDGET_ERROR_NONE); - return (int)nodisplay; } +/* deprecated, always return need_of_frame as false */ EAPI int widget_service_get_need_of_frame(const char *pkgid, widget_size_type_e size_type, bool *need_of_frame) { - /* deprecated */ - return WIDGET_ERROR_NOT_SUPPORTED; + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (!pkgid) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + *need_of_frame = false; + + return WIDGET_ERROR_NONE; } +/* deprecated, always return need_of_touch_event as false */ EAPI int widget_service_get_need_of_touch_effect(const char *pkgid, widget_size_type_e size_type, bool *need_of_touch_event) { - /* deprecated */ - return WIDGET_ERROR_NOT_SUPPORTED; + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (!pkgid) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + *need_of_touch_event = false; + + return WIDGET_ERROR_NONE; } +/* deprecated, always return need_of_mouse_event as false */ EAPI int widget_service_get_need_of_mouse_event(const char *pkgid, widget_size_type_e size_type, bool *need_of_mouse_event) { - /* deprecated */ - return WIDGET_ERROR_NOT_SUPPORTED; + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (!pkgid) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + *need_of_mouse_event = false; + return WIDGET_ERROR_NONE; } EAPI char *widget_service_get_preview_image_path(const char *widget_id, @@ -1032,20 +1112,105 @@ EAPI int widget_service_get_size_type(int width, int height, EAPI int widget_service_get_content_of_widget_instance(const char *widget_id, const char *widget_instance_id, bundle **b) { - return WIDGET_ERROR_NOT_SUPPORTED; + widget_instance_h instance; + bundle *kb = NULL; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (widget_id == NULL || widget_instance_id == NULL || b == NULL) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + instance = widget_instance_get_instance(widget_id, widget_instance_id); + + if (instance) { + widget_instance_get_content(instance, &kb); + if (kb) { + *b = bundle_dup(kb); + widget_instance_unref(instance); + return WIDGET_ERROR_NONE; + } + } + + return WIDGET_ERROR_INVALID_PARAMETER; +} + +struct instance_cb { + widget_instance_list_cb cb; + void *data; +}; + +static int __instance_list_cb(const char *widget_id, const char *instance_id, void *data) +{ + struct instance_cb *cb_data = (struct instance_cb *)data; + + if (cb_data && cb_data->cb) + return cb_data->cb(widget_id, instance_id, cb_data->data); + + return -1; } EAPI int widget_service_get_widget_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data) { - return WIDGET_ERROR_NOT_SUPPORTED; + struct instance_cb cb_data; + int ret = WIDGET_ERROR_NONE; + + cb_data.cb = cb; + cb_data.data = data; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (widget_id == NULL || cb == NULL) { + _E("inavlid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + ret = widget_instance_get_instance_list(widget_id, __instance_list_cb, &cb_data); + + return ret < 0 ? (ret == -2 ? WIDGET_ERROR_PERMISSION_DENIED : WIDGET_ERROR_NOT_EXIST) : WIDGET_ERROR_NONE; } EAPI int widget_service_set_lifecycle_event_cb(const char *widget_id, widget_lifecycle_event_cb cb, void *data) { - return WIDGET_ERROR_NOT_SUPPORTED; + int ret = WIDGET_ERROR_NONE; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (widget_id == NULL || cb == NULL) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + /* TODO */ + + return ret; } EAPI int widget_service_unset_lifecycle_event_cb(const char *widget_id, void **user_data) { - return WIDGET_ERROR_NOT_SUPPORTED; + int ret = WIDGET_ERROR_NONE; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (widget_id == NULL) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + /* TODO */ + + return ret; } diff --git a/tool/widget_test.c b/tool/widget_test.c new file mode 100644 index 0000000..fe4d8ee --- /dev/null +++ b/tool/widget_test.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +typedef int (*test_fn)(int argc, char **argv); + +typedef struct _test_func_t { + const char *cmd; + test_fn fn; + const char *usage; +} test_func_t; + +int get_pkg_id(int argc, char **argv) +{ + char *pkg_id; + + if (argc < 1) + return -1; + + pkg_id = widget_service_get_package_id(argv[2]); + printf("pkg id: %s", pkg_id); + + return 0; +} + +test_func_t test_func[] = { + {"get_pkg_id", get_pkg_id, ""} +}; + +static void print_usage(char *pname) +{ + int i = 0; + printf("[usage] %s ...\n", pname); + printf(" - available cmd list \n"); + + for (i = 0; i < sizeof(test_func) / sizeof(test_func_t); i++) { + printf("%s %s %s\n\n", pname, test_func[i].cmd, test_func[i].usage); + } + printf(" - end cmd list\n"); +} + +int main(int argc, char **argv) +{ + int i = 0; + + if (argc < 2) { + print_usage(argv[0]); + exit(0); + } + + for (i = 0; i < (sizeof(test_func) / sizeof(test_func_t)); i++) { + if (strcmp(test_func[i].cmd, argv[1]) == 0) { + return test_func[i].fn(argc, argv); + } + } + + print_usage(argv[0]); + + return 0; +} -- 2.7.4 From 58d34a7388c3c5b5c116c54c28abda28f826e3bb Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Wed, 16 Mar 2016 18:55:43 +0900 Subject: [PATCH 03/16] fix utc errors Change-Id: I05fea32682242dc0ddd538aac44723128d1d34e8 Signed-off-by: Daehyeon Jung --- include/widget_instance.h | 1 + src/widget_instance.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-- src/widget_service.c | 22 +++++++----------- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/include/widget_instance.h b/include/widget_instance.h index ef885e1..7add9cb 100644 --- a/include/widget_instance.h +++ b/include/widget_instance.h @@ -35,6 +35,7 @@ extern "C" { #define WIDGET_K_WIDTH "__WIDGET_WIDTH__" #define WIDGET_K_HEIGHT "__WIDGET_HEIGHT__" #define WIDGET_K_REASON "__WIDGET_REASON__" +#define WIDGET_K_PERIOD "__WIDGET_PERIOD__" typedef enum widget_instance_event { WIDGET_INSTANCE_EVENT_CREATE = 0, diff --git a/src/widget_instance.c b/src/widget_instance.c index 0580411..b5436d6 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -845,12 +845,66 @@ EAPI int widget_instance_get_period(widget_instance_h instance, double *period) EAPI int widget_instance_change_period(widget_instance_h instance, double period) { - return 0; + int ret; + bundle *b; + + if (!instance) + return -1; + + b = bundle_create(); + if (!b) { + _E("out of memory"); + return -1; + } + + bundle_add_str(b, WIDGET_K_OPERATION, "period"); + bundle_add_byte(b, WIDGET_K_PERIOD, &period, sizeof(double)); + + ret = __send_aul_cmd(instance->widget_id, instance->id, b); + + bundle_free(b); + + if (ret > 0) { + if (instance->pid != ret) { + _E("instance %s(%d) has been launched with different pid."); + instance->pid = ret; + } + } + + return ret; } EAPI int widget_instance_trigger_update(widget_instance_h instance, bundle *b, int force) { - return 0; + int ret; + bundle *kb = b; + + if (!instance) + return -1; + + if (!kb) { + kb = bundle_create(); + if (!kb) { + _E("out of memory"); + return -1; + } + } + + bundle_add_str(kb, WIDGET_K_OPERATION, "update"); + + ret = __send_aul_cmd(instance->widget_id, instance->id, kb); + + if (!b) + bundle_free(kb); + + if (ret > 0) { + if (instance->pid != ret) { + _E("instance %s(%d) has been launched with different pid."); + instance->pid = ret; + } + } + + return ret; } EAPI widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id) diff --git a/src/widget_service.c b/src/widget_service.c index 91bb143..b7d9e5e 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -262,6 +262,9 @@ static int _get_widget_supported_sizes(const char *widget_id, int *cnt, EAPI int widget_service_change_period(const char *pkgname, const char *id, double period) { + widget_instance_h instance; + int ret; + if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; @@ -272,9 +275,6 @@ EAPI int widget_service_change_period(const char *pkgname, const char *id, doubl return WIDGET_ERROR_INVALID_PARAMETER; } - widget_instance_h instance; - int ret; - instance = widget_instance_get_instance(pkgname, id); if (!instance) { @@ -291,19 +291,19 @@ EAPI int widget_service_change_period(const char *pkgname, const char *id, doubl EAPI int widget_service_trigger_update(const char *widget_id, const char *id, bundle *b, int force) { + widget_instance_h instance; + int ret; + if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } - if (!widget_id || !id || !b) { + if (!widget_id) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } - widget_instance_h instance; - int ret; - instance = widget_instance_get_instance(widget_id, id); if (!instance) { _E("instance not exists or out of bound(package)"); @@ -1186,7 +1186,7 @@ EAPI int widget_service_set_lifecycle_event_cb(const char *widget_id, widget_lif return WIDGET_ERROR_NOT_SUPPORTED; } - if (widget_id == NULL || cb == NULL) { + if (cb == NULL) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } @@ -1204,12 +1204,6 @@ EAPI int widget_service_unset_lifecycle_event_cb(const char *widget_id, void **u _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } - - if (widget_id == NULL) { - _E("invalid parameter"); - return WIDGET_ERROR_INVALID_PARAMETER; - } - /* TODO */ return ret; -- 2.7.4 From a8d4aef955a5afaaacea03c0cd495298eda08ed9 Mon Sep 17 00:00:00 2001 From: "SukHyung, Kang" Date: Fri, 18 Mar 2016 10:33:24 +0900 Subject: [PATCH 04/16] Use thread-safe functions Change-Id: I2011ebc0bf534098f2732ab05d65d2bc12d1253c Signed-off-by: SukHyung, Kang --- src/widget_conf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/widget_conf.c b/src/widget_conf.c index e1bc98d..9ce3364 100644 --- a/src/widget_conf.c +++ b/src/widget_conf.c @@ -705,7 +705,8 @@ static char *parse_handler(const char *buffer) static char *find_input_device_by_path(const char *name) { DIR *dir; - struct dirent *entry; + struct dirent entry; + struct dirent *result; char path[PATH_MAX]; char *ptr; int len; @@ -725,13 +726,14 @@ static char *find_input_device_by_path(const char *name) ptr = path + len; len = PATH_MAX - len - 1; - while ((entry = readdir(dir))) { - if (entry->d_name[0] == '.' && - (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) { + while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) { + if (result->d_name[0] == '.' && + (result->d_name[1] == '\0' + || (result->d_name[1] == '.' && result->d_name[2] == '\0'))) { continue; } - strncpy(ptr, entry->d_name, len); + strncpy(ptr, result->d_name, len); ptr[len] = '\0'; fd = open(path, O_RDONLY); -- 2.7.4 From 22bb158d2ffdcc213e7367d6ea21977260c60429 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 23 Mar 2016 12:10:45 +0900 Subject: [PATCH 05/16] Adjust multi-user environment Change-Id: Iee48c7ad9d3fafd6f7f4b4b3b21c7715e8447372 Signed-off-by: Sangyoon Jang --- src/widget_service.c | 521 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 345 insertions(+), 176 deletions(-) diff --git a/src/widget_service.c b/src/widget_service.c index b7d9e5e..ff4343d 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -14,12 +14,14 @@ * limitations under the License. */ +#include #include #include #include #include #include +#include #include #include @@ -33,6 +35,8 @@ #include "widget_instance.h" #include "widget_service.h" +#define MAX_BUF_SIZE 4096 + static inline bool _is_widget_feature_enabled(void) { static bool feature = false; @@ -54,10 +58,29 @@ static inline bool _is_widget_feature_enabled(void) return feature; } +#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 const char *_get_db_path(uid_t uid) { - /* TODO: tizenglobalapp */ - return tzplatform_mkpath(TZ_USER_DB, ".widget.db"); + 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 path; } static sqlite3 *_open_db(uid_t uid) @@ -195,8 +218,8 @@ static int _convert_to_support_size_ratio(int width, int height, int *w, int *h) return 0; } -static int _get_widget_supported_sizes(const char *widget_id, int *cnt, - int **w, int **h) +static int _get_widget_supported_sizes(const char *widget_id, uid_t uid, + int *cnt, int **w, int **h) { static const char query[] = "SELECT width, height FROM support_size WHERE classid=?"; @@ -208,7 +231,7 @@ static int _get_widget_supported_sizes(const char *widget_id, int *cnt, int *width; int *height; - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; @@ -225,7 +248,6 @@ static int _get_widget_supported_sizes(const char *widget_id, int *cnt, count++; if (count == 0) { - _E("cannot find supported sizes for widget %s", widget_id); sqlite3_finalize(stmt); sqlite3_close_v2(db); *cnt = 0; @@ -317,46 +339,63 @@ EAPI int widget_service_trigger_update(const char *widget_id, const char *id, bu return ret; } -EAPI int widget_service_get_widget_list(widget_list_cb cb, void *data) +struct widget_list_item { + char *classid; + char *pkgid; + int is_prime; +}; + +static void __free_widget_list(gpointer data) +{ + struct widget_list_item *item = (struct widget_list_item *)data; + + free(item->classid); + free(item->pkgid); + free(item); +} + +static int _get_widget_list(const char *pkgid, uid_t uid, GList **list) { static const char query[] = "SELECT classid, pkgid FROM widget_class"; + static const char query_where[] = + " WHERE pkgid = ?"; + char query_buf[MAX_BUF_SIZE]; int ret; + int len; sqlite3 *db; sqlite3_stmt *stmt; - char *classid; - char *pkgid; - - if (!_is_widget_feature_enabled()) { - _E("not supported"); - return WIDGET_ERROR_NOT_SUPPORTED; - } + struct widget_list_item *item; - if (cb == NULL) { - _E("invalid parameter"); - return WIDGET_ERROR_INVALID_PARAMETER; - } + len = snprintf(query_buf, sizeof(query_buf), "%s", query); + if (pkgid != NULL) + strncat(query_buf, query_where, MAX_BUF_SIZE - len - 1); - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; - ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + ret = sqlite3_prepare_v2(db, query_buf, strlen(query_buf), &stmt, NULL); if (ret != SQLITE_OK) { _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; } + if (pkgid != NULL) + sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC); + while (sqlite3_step(stmt) == SQLITE_ROW) { - _get_column_str(stmt, 0, &classid); - _get_column_str(stmt, 0, &pkgid); - /* TODO: get 'is_prime' */ - ret = cb(pkgid, classid, 0, data); - free(classid); - free(pkgid); - if (ret != WIDGET_ERROR_NONE) - break; + item = calloc(1, sizeof(struct widget_list_item)); + if (item == NULL) { + _E("out of memory"); + return WIDGET_ERROR_OUT_OF_MEMORY; + } + + _get_column_str(stmt, 0, &item->classid); + _get_column_str(stmt, 1, &item->pkgid); + + *list = g_list_append(*list, item); } sqlite3_finalize(stmt); @@ -365,55 +404,78 @@ EAPI int widget_service_get_widget_list(widget_list_cb cb, void *data) return WIDGET_ERROR_NONE; } -EAPI int widget_service_get_widget_list_by_pkgid(const char *pkgid, - widget_list_by_pkgid_cb cb, void *data) +EAPI int widget_service_get_widget_list(widget_list_cb cb, void *data) { - static const char query[] = - "SELECT classid FROM widget_class WHERE pkgid=?"; int ret; - sqlite3 *db; - sqlite3_stmt *stmt; - char *classid; + GList *list = NULL; + GList *tmp; + struct widget_list_item *item; if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } - if (pkgid == NULL || cb == NULL) { + if (cb == NULL) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } - db = _open_db(getuid()); - if (db == NULL) - return WIDGET_ERROR_IO_ERROR; + ret = _get_widget_list(NULL, getuid(), &list); + if (ret == WIDGET_ERROR_NONE) + ret = _get_widget_list(NULL, GLOBALAPP_USER, &list); - ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); - if (ret != SQLITE_OK) { - _E("prepare error: %s", sqlite3_errmsg(db)); - sqlite3_close_v2(db); - return WIDGET_ERROR_FAULT; + for (tmp = list; tmp; tmp = tmp->next) { + item = (struct widget_list_item *)tmp->data; + /* TODO: get 'is_prime' */ + if (cb(item->pkgid, item->classid, item->is_prime, data) + != WIDGET_ERROR_NONE) + break; } - sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC); + ret = g_list_length(list); + g_list_free_full(list, __free_widget_list); - while (sqlite3_step(stmt) == SQLITE_ROW) { - _get_column_str(stmt, 0, &classid); + return ret; +} + +EAPI int widget_service_get_widget_list_by_pkgid(const char *pkgid, + widget_list_by_pkgid_cb cb, void *data) +{ + int ret; + GList *list = NULL; + GList *tmp; + struct widget_list_item *item; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + return WIDGET_ERROR_NOT_SUPPORTED; + } + + if (pkgid == NULL || cb == NULL) { + _E("invalid parameter"); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + ret = _get_widget_list(pkgid, getuid(), &list); + if (ret == WIDGET_ERROR_NONE) + ret = _get_widget_list(pkgid, GLOBALAPP_USER, &list); + + for (tmp = list; tmp; tmp = tmp->next) { + item = (struct widget_list_item *)tmp->data; /* TODO: get 'is_prime' */ - ret = cb(classid, 0, data); - free(classid); - if (ret != WIDGET_ERROR_NONE) + if (cb(item->classid, item->is_prime, data) + != WIDGET_ERROR_NONE) break; } - sqlite3_finalize(stmt); - sqlite3_close_v2(db); + ret = g_list_length(list); + g_list_free_full(list, __free_widget_list); - return WIDGET_ERROR_NONE; + return ret; } -EAPI char *widget_service_get_main_app_id(const char *widget_id) +static char *_get_main_app_id(const char *widget_id, uid_t uid) { static const char query[] = "SELECT pkgid FROM widget_class WHERE classid=?"; @@ -425,19 +487,7 @@ EAPI char *widget_service_get_main_app_id(const char *widget_id) char *mainappid; char *appid; - if (!_is_widget_feature_enabled()) { - _E("not supported"); - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - if (widget_id == NULL) { - _E("invalid parameter"); - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -492,6 +542,29 @@ EAPI char *widget_service_get_main_app_id(const char *widget_id) return appid; } +EAPI char *widget_service_get_main_app_id(const char *widget_id) +{ + char *appid; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + if (widget_id == NULL) { + _E("invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return NULL; + } + + appid = _get_main_app_id(widget_id, getuid()); + if (appid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + appid = _get_main_app_id(widget_id, GLOBALAPP_USER); + + return appid; +} + EAPI int widget_service_get_supported_size_types(const char *widget_id, int *cnt, int **types) { @@ -511,8 +584,14 @@ EAPI int widget_service_get_supported_size_types(const char *widget_id, return WIDGET_ERROR_INVALID_PARAMETER; } - ret = _get_widget_supported_sizes(widget_id, cnt, &width, &height); + ret = _get_widget_supported_sizes(widget_id, getuid(), cnt, + &width, &height); + if (ret == WIDGET_ERROR_NOT_EXIST) + ret = _get_widget_supported_sizes(widget_id, GLOBALAPP_USER, + cnt, &width, &height); + if (ret == WIDGET_ERROR_NOT_EXIST) { + _E("cannot find supported sizes for widget %s", widget_id); *types = NULL; return WIDGET_ERROR_NONE; } else if (ret != WIDGET_ERROR_NONE) { @@ -529,13 +608,13 @@ EAPI int widget_service_get_supported_size_types(const char *widget_id, for (i = 0; i < (*cnt); i++) { if (_get_supported_size_type(width[i], height[i], &type)) { - free(types); + free(*types); free(width); free(height); return WIDGET_ERROR_NOT_SUPPORTED; } - *types[i] = type; + (*types)[i] = type; } free(width); @@ -544,7 +623,7 @@ EAPI int widget_service_get_supported_size_types(const char *widget_id, return WIDGET_ERROR_NONE; } -EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) +static char *_get_app_id_of_setup_app(const char *widget_id, uid_t uid) { static const char query[] = "SELECT setup_appid FROM widget_class WHERE classid=?"; @@ -553,19 +632,7 @@ EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) sqlite3_stmt *stmt; char *appid; - if (!_is_widget_feature_enabled()) { - _E("not supported"); - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - if (widget_id == NULL) { - _E("invalid parameter"); - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -602,32 +669,44 @@ EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) return appid; } -EAPI int widget_service_get_nodisplay(const char *widget_id) +EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) { - static const char query[] = - "SELECT appid FROM widget_class WHERE classid=?"; - int ret; - sqlite3 *db; - sqlite3_stmt *stmt; char *appid; - pkgmgrinfo_appinfo_h appinfo; - bool nodisplay; if (!_is_widget_feature_enabled()) { _E("not supported"); - return WIDGET_ERROR_NOT_SUPPORTED; + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; } if (widget_id == NULL) { _E("invalid parameter"); set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return 0; + return NULL; } - db = _open_db(getuid()); + appid = _get_app_id_of_setup_app(widget_id, getuid()); + if (appid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + appid = _get_app_id_of_setup_app(widget_id, GLOBALAPP_USER); + + return appid; +} + +static bool _get_nodisplay(const char *widget_id, uid_t uid) +{ + static const char query[] = + "SELECT appid FROM widget_class WHERE classid=?"; + int ret; + sqlite3 *db; + sqlite3_stmt *stmt; + char *appid; + pkgmgrinfo_appinfo_h appinfo; + bool nodisplay; + + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); - return 0; + return false; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); @@ -635,7 +714,7 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); - return 0; + return false; } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); @@ -648,7 +727,7 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); - return 0; + return false; } _get_column_str(stmt, 0, &appid); @@ -660,7 +739,7 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) free(appid); if (ret != PMINFO_R_OK) { set_last_result(WIDGET_ERROR_FAULT); - return 0; + return false; } ret = pkgmgrinfo_appinfo_is_nodisplay(appinfo, &nodisplay); @@ -668,10 +747,34 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) if (ret != PMINFO_R_OK) { _E("failed to get nodisplay of widget %s", widget_id); set_last_result(WIDGET_ERROR_FAULT); - return 0; + return false; } set_last_result(WIDGET_ERROR_NONE); + + return nodisplay; +} + +EAPI int widget_service_get_nodisplay(const char *widget_id) +{ + bool nodisplay; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return 0; + } + + if (widget_id == NULL) { + _E("invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return 0; + } + + nodisplay = _get_nodisplay(widget_id, getuid()); + if (get_last_result() == WIDGET_ERROR_NOT_EXIST) + nodisplay = _get_nodisplay(widget_id, GLOBALAPP_USER); + return (int)nodisplay; } @@ -728,8 +831,8 @@ EAPI int widget_service_get_need_of_mouse_event(const char *pkgid, widget_size_t return WIDGET_ERROR_NONE; } -EAPI char *widget_service_get_preview_image_path(const char *widget_id, - widget_size_type_e size_type) +static char *_get_preview_image_path(const char *widget_id, int width, + int height, uid_t uid) { static const char query[] = "SELECT preview FROM support_size WHERE " @@ -737,36 +840,9 @@ EAPI char *widget_service_get_preview_image_path(const char *widget_id, int ret; sqlite3 *db; sqlite3_stmt *stmt; - int width = -1; - int height = -1; - int w = -1; - int h = -1; char *path; - if (!_is_widget_feature_enabled()) { - _E("not supported"); - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - /* TODO: validate size_type */ - if (widget_id == NULL) { - _E("invalid parameter"); - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - if (_get_supported_size(size_type, &width, &height)) { - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - if (_convert_to_support_size_ratio(width, height, &w, &h)) { - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -781,8 +857,8 @@ EAPI char *widget_service_get_preview_image_path(const char *widget_id, } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 2, w); - sqlite3_bind_int(stmt, 3, h); + sqlite3_bind_int(stmt, 2, width); + sqlite3_bind_int(stmt, 3, height); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { @@ -805,16 +881,14 @@ EAPI char *widget_service_get_preview_image_path(const char *widget_id, return path; } -EAPI char *widget_service_get_icon(const char *widget_id, const char *lang) +EAPI char *widget_service_get_preview_image_path(const char *widget_id, + widget_size_type_e size_type) { - static const char query[] = - "SELECT icon FROM icon " - "WHERE classid=? AND (locale=? OR locale IS NULL) " - "ORDER BY locale DESC"; - int ret; - sqlite3 *db; - sqlite3_stmt *stmt; - char *icon; + char *path; + int width = -1; + int height = -1; + int w = -1; + int h = -1; if (!_is_widget_feature_enabled()) { _E("not supported"); @@ -822,13 +896,42 @@ EAPI char *widget_service_get_icon(const char *widget_id, const char *lang) return NULL; } + /* TODO: validate size_type */ if (widget_id == NULL) { _E("invalid parameter"); set_last_result(WIDGET_ERROR_INVALID_PARAMETER); return NULL; } - db = _open_db(getuid()); + if (_get_supported_size(size_type, &width, &height)) { + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + if (_convert_to_support_size_ratio(width, height, &w, &h)) { + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + path = _get_preview_image_path(widget_id, w, h, getuid()); + if (path == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + path = _get_preview_image_path(widget_id, w, h, GLOBALAPP_USER); + + return path; +} + +static char *_get_icon(const char *widget_id, const char *lang, uid_t uid) +{ + static const char query[] = + "SELECT icon FROM icon " + "WHERE classid=? AND (locale=? OR locale IS NULL) " + "ORDER BY locale DESC"; + int ret; + sqlite3 *db; + sqlite3_stmt *stmt; + char *icon; + + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -872,16 +975,9 @@ EAPI char *widget_service_get_icon(const char *widget_id, const char *lang) return icon; } -EAPI char *widget_service_get_name(const char *widget_id, const char *lang) +EAPI char *widget_service_get_icon(const char *widget_id, const char *lang) { - static const char query[] = - "SELECT label FROM label " - "WHERE classid=? AND (locale=? OR locale IS NULL) " - "ORDER BY locale DESC"; - int ret; - sqlite3 *db; - sqlite3_stmt *stmt; - char *label; + char *icon; if (!_is_widget_feature_enabled()) { _E("not supported"); @@ -895,7 +991,25 @@ EAPI char *widget_service_get_name(const char *widget_id, const char *lang) return NULL; } - db = _open_db(getuid()); + icon = _get_icon(widget_id, lang, getuid()); + if (icon == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + icon = _get_icon(widget_id, lang, GLOBALAPP_USER); + + return icon; +} + +static char *_get_name(const char *widget_id, const char *lang, uid_t uid) +{ + static const char query[] = + "SELECT label FROM label " + "WHERE classid=? AND (locale=? OR locale IS NULL) " + "ORDER BY locale DESC"; + int ret; + sqlite3 *db; + sqlite3_stmt *stmt; + char *label; + + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -938,11 +1052,36 @@ EAPI char *widget_service_get_name(const char *widget_id, const char *lang) set_last_result(WIDGET_ERROR_NONE); return label; + +} + +EAPI char *widget_service_get_name(const char *widget_id, const char *lang) +{ + char *name; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + if (widget_id == NULL) { + _E("invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return NULL; + } + name = _get_name(widget_id, lang, getuid()); + if (name == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + name = _get_name(widget_id, lang, GLOBALAPP_USER); + + return name; } EAPI int widget_service_get_supported_sizes(const char *widget_id, int *cnt, int **w, int **h) { + int ret; + if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; @@ -953,10 +1092,18 @@ EAPI int widget_service_get_supported_sizes(const char *widget_id, int *cnt, return WIDGET_ERROR_INVALID_PARAMETER; } - return _get_widget_supported_sizes(widget_id, cnt, w, h); + ret = _get_widget_supported_sizes(widget_id, getuid(), cnt, w, h); + if (ret == WIDGET_ERROR_NOT_EXIST) + ret = _get_widget_supported_sizes(widget_id, GLOBALAPP_USER, + cnt, w, h); + + if (ret == WIDGET_ERROR_NOT_EXIST) + _E("cannot find supported sizes for widget %s", widget_id); + + return ret; } -EAPI char *widget_service_get_widget_id(const char *appid) +static char *_get_widget_id(const char *appid, uid_t uid) { static const char query[] = "SELECT classid FROM widget_class WHERE appid=?"; @@ -965,19 +1112,7 @@ EAPI char *widget_service_get_widget_id(const char *appid) sqlite3_stmt *stmt; char *classid; - if (!_is_widget_feature_enabled()) { - _E("not supported"); - set_last_result(WIDGET_ERROR_NOT_SUPPORTED); - return NULL; - } - - if (appid == NULL) { - _E("invalid parameter"); - set_last_result(WIDGET_ERROR_INVALID_PARAMETER); - return NULL; - } - - db = _open_db(getuid()); + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -1014,14 +1149,9 @@ EAPI char *widget_service_get_widget_id(const char *appid) return classid; } -EAPI char *widget_service_get_package_id(const char *widget_id) +EAPI char *widget_service_get_widget_id(const char *appid) { - static const char query[] = - "SELECT pkgid FROM widget_class WHERE classid=?"; - int ret; - sqlite3 *db; - sqlite3_stmt *stmt; - char *pkgid; + char *classid; if (!_is_widget_feature_enabled()) { _E("not supported"); @@ -1029,13 +1159,29 @@ EAPI char *widget_service_get_package_id(const char *widget_id) return NULL; } - if (widget_id == NULL) { + if (appid == NULL) { _E("invalid parameter"); set_last_result(WIDGET_ERROR_INVALID_PARAMETER); return NULL; } - db = _open_db(getuid()); + classid = _get_widget_id(appid, getuid()); + if (classid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + classid = _get_widget_id(appid, GLOBALAPP_USER); + + return classid; +} + +static char *_get_package_id(const char *widget_id, uid_t uid) +{ + static const char query[] = + "SELECT pkgid FROM widget_class WHERE classid=?"; + int ret; + sqlite3 *db; + sqlite3_stmt *stmt; + char *pkgid; + + db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; @@ -1072,6 +1218,29 @@ EAPI char *widget_service_get_package_id(const char *widget_id) return pkgid; } +EAPI char *widget_service_get_package_id(const char *widget_id) +{ + char *pkgid; + + if (!_is_widget_feature_enabled()) { + _E("not supported"); + set_last_result(WIDGET_ERROR_NOT_SUPPORTED); + return NULL; + } + + if (widget_id == NULL) { + _E("invalid parameter"); + set_last_result(WIDGET_ERROR_INVALID_PARAMETER); + return NULL; + } + + pkgid = _get_package_id(widget_id, getuid()); + if (pkgid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) + pkgid = _get_package_id(widget_id, GLOBALAPP_USER); + + return pkgid; +} + EAPI int widget_service_get_size(widget_size_type_e type, int *width, int *height) { -- 2.7.4 From 918011aa119a6491920ee810ea265181bf7fd201 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Thu, 24 Mar 2016 19:56:01 +0900 Subject: [PATCH 06/16] Store nodisplay value to widget db Change-Id: I78a21a1426938a9015f9ee8c45b9e747e6d6c704 --- parser/widget.sql | 1 + parser/widget_plugin_parser.c | 6 ++++++ parser/widget_plugin_parser_db.c | 5 +++-- parser/widget_plugin_parser_internal.h | 1 + src/widget_service.c | 35 +++++++++------------------------- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/parser/widget.sql b/parser/widget.sql index d51fc9b..c1d9134 100644 --- a/parser/widget.sql +++ b/parser/widget.sql @@ -10,6 +10,7 @@ CREATE TABLE widget_class ( setup_appid TEXT, appid TEXT NOT NULL, pkgid TEXT NOT NULL, + nodisplay INTEGER DEFAULT 0, PRIMARY KEY(classid) ); diff --git a/parser/widget_plugin_parser.c b/parser/widget_plugin_parser.c index e68c0e4..710ee33 100644 --- a/parser/widget_plugin_parser.c +++ b/parser/widget_plugin_parser.c @@ -257,6 +257,12 @@ static int _parse_widget_application(xmlNode *node, GList **list) if (val) wc->update_period = atoi(val); + val = _get_attribute(node, "nodisplay"); + if (val && strncmp(val, "true", strlen("true")) == 0) + wc->nodisplay = 1; + else + wc->nodisplay = 0; + wc->setup_appid = _get_attribute(node, "setup-appid"); for (tmp = node->children; tmp; tmp = tmp->next) { diff --git a/parser/widget_plugin_parser_db.c b/parser/widget_plugin_parser_db.c index 4d2c5c0..6c6c62e 100644 --- a/parser/widget_plugin_parser_db.c +++ b/parser/widget_plugin_parser_db.c @@ -164,8 +164,8 @@ 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 (?, ?, ?, ?, ?)"; + "setup_appid, appid, pkgid, nodisplay) " + "VALUES (?, ?, ?, ?, ?, ?)"; GList *tmp; struct widget_class *wc; sqlite3_stmt *stmt = NULL; @@ -185,6 +185,7 @@ static int _insert_widget_class(sqlite3 *db, const char *pkgid, GList *wcs) _bind_text(stmt, idx++, wc->setup_appid); _bind_text(stmt, idx++, wc->appid); _bind_text(stmt, idx++, pkgid); + sqlite3_bind_int(stmt, idx++, wc->nodisplay); ret = sqlite3_step(stmt); if (ret != SQLITE_DONE) { diff --git a/parser/widget_plugin_parser_internal.h b/parser/widget_plugin_parser_internal.h index 8f274de..44f0fdb 100644 --- a/parser/widget_plugin_parser_internal.h +++ b/parser/widget_plugin_parser_internal.h @@ -39,6 +39,7 @@ struct widget_class { int update_period; char *setup_appid; char *appid; + int nodisplay; GList *support_size; GList *label; GList *icon; diff --git a/src/widget_service.c b/src/widget_service.c index ff4343d..31b56d9 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -692,21 +692,19 @@ EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) return appid; } -static bool _get_nodisplay(const char *widget_id, uid_t uid) +static int _get_nodisplay(const char *widget_id, uid_t uid) { static const char query[] = - "SELECT appid FROM widget_class WHERE classid=?"; + "SELECT nodisplay FROM widget_class WHERE classid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; - char *appid; - pkgmgrinfo_appinfo_h appinfo; - bool nodisplay; + int nodisplay = 0; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); - return false; + return 0; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); @@ -714,7 +712,7 @@ static bool _get_nodisplay(const char *widget_id, uid_t uid) _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); - return false; + return 0; } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); @@ -727,29 +725,14 @@ static bool _get_nodisplay(const char *widget_id, uid_t uid) /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); - return false; + return 0; } - _get_column_str(stmt, 0, &appid); + _get_column_int(stmt, 0, &nodisplay); sqlite3_finalize(stmt); sqlite3_close_v2(db); - ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &appinfo); - free(appid); - if (ret != PMINFO_R_OK) { - set_last_result(WIDGET_ERROR_FAULT); - return false; - } - - ret = pkgmgrinfo_appinfo_is_nodisplay(appinfo, &nodisplay); - pkgmgrinfo_appinfo_destroy_appinfo(appinfo); - if (ret != PMINFO_R_OK) { - _E("failed to get nodisplay of widget %s", widget_id); - set_last_result(WIDGET_ERROR_FAULT); - return false; - } - set_last_result(WIDGET_ERROR_NONE); return nodisplay; @@ -757,7 +740,7 @@ static bool _get_nodisplay(const char *widget_id, uid_t uid) EAPI int widget_service_get_nodisplay(const char *widget_id) { - bool nodisplay; + int nodisplay; if (!_is_widget_feature_enabled()) { _E("not supported"); @@ -775,7 +758,7 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) if (get_last_result() == WIDGET_ERROR_NOT_EXIST) nodisplay = _get_nodisplay(widget_id, GLOBALAPP_USER); - return (int)nodisplay; + return nodisplay; } /* deprecated, always return need_of_frame as false */ -- 2.7.4 From dbbc459b76db26824fa7cfefed755bf992e26f8e Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Thu, 24 Mar 2016 18:13:29 +0900 Subject: [PATCH 07/16] Add widget_service_(un)set_lifecycle_cb Change-Id: Idf80d5d7530fb92b083debe59050d8b2c3bd2892 Signed-off-by: Daehyeon Jung --- include/widget_instance.h | 3 +- src/widget_instance.c | 118 ++++++++++++++++++++++++++++++++++++++++++++-- src/widget_service.c | 88 ++++++++++++++++++++++++++++++++-- 3 files changed, 201 insertions(+), 8 deletions(-) diff --git a/include/widget_instance.h b/include/widget_instance.h index 7add9cb..6a468ff 100644 --- a/include/widget_instance.h +++ b/include/widget_instance.h @@ -72,7 +72,8 @@ void widget_instance_unref(widget_instance_h instance); widget_instance_h widget_instance_ref(widget_instance_h instance); int widget_instance_change_period(widget_instance_h instance, double period); int widget_instance_trigger_update(widget_instance_h instance, bundle *b, int force); -int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, int status, const char *instance_id, void *data), void *data); +int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, int status, void *data), void *data); +int widget_instance_unlisten_status(const char *widget_id); #ifdef __cplusplus } diff --git a/src/widget_instance.c b/src/widget_instance.c index b5436d6..12b188e 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -78,6 +78,14 @@ static sqlite3 *_widget_db = NULL; static char *viewer_appid = NULL; static aul_app_com_connection_h conn = NULL; +static GHashTable *lifecycle_tbl; +static int is_update_hook_registered; + +struct lifecycle_local_s { + char *widget_id; + int (*cb)(const char *, const char *, int, void *); + void *data; +}; #define QUERY_CREATE_TABLE_WIDGET \ "create table if not exists widget_instance" \ @@ -85,6 +93,7 @@ static aul_app_com_connection_h conn = NULL; "viewer_id text, " \ "content_info text, " \ "instance_id text, " \ + "status integer, " \ "PRIMARY KEY(instance_id)) " static int __init(bool readonly) @@ -371,8 +380,8 @@ static int __load_instance_list() 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 insert_query[] = "INSERT INTO widget_instance(widget_id, viewer_id, content_info, instance_id, status) VALUES(?,?,?,?,?)"; + const char update_query[] = "UPDATE widget_instance SET content_info=? status=? WHERE instance_id=?"; const char delete_query[] = "DELETE FROM widget_instance WHERE instance_id=?"; sqlite3_stmt* p_statement; struct widget_app *app = NULL; @@ -422,7 +431,8 @@ static int __update_instance_info(struct _widget_instance *instance) } sqlite3_bind_text(p_statement, 1, content, -1, SQLITE_TRANSIENT); - sqlite3_bind_text(p_statement, 2, instance->id, -1, SQLITE_TRANSIENT); + sqlite3_bind_int(p_statement, 2, instance->status); + sqlite3_bind_text(p_statement, 3, instance->id, -1, SQLITE_TRANSIENT); } } else { app = __pick_app(instance->widget_id); @@ -444,6 +454,7 @@ static int __update_instance_info(struct _widget_instance *instance) 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); + sqlite3_bind_int(p_statement, 5, instance->status); } rc = sqlite3_step(p_statement); @@ -972,4 +983,105 @@ EAPI widget_instance_h widget_instance_ref(widget_instance_h instance) return instance; } +static void __update_cb(void *data, int action, char const *db_name, char const *table_name, sqlite_int64 rowid) +{ + char *buf; + int ret; + sqlite3_stmt* p_statement; + char *widget_id; + char *instance_id; + int status; + struct lifecycle_local_s *cb_info; + + buf = sqlite3_mprintf("SELECT widget_id, instance_id, status FROM widget_instance WHERE rowid='%lld';", rowid); + if (buf == NULL) + return; + + ret = sqlite3_prepare_v2(_widget_db, buf, strlen(buf), &p_statement, NULL); + if (ret != SQLITE_OK) { + _E("sqlite3 error [%d] : <%s> executing statement\n", ret, sqlite3_errmsg(_widget_db)); + return; + } + + ret = sqlite3_step(p_statement); + if (ret != SQLITE_ROW) { + _E("step error: %s", sqlite3_errmsg(_widget_db)); + sqlite3_finalize(p_statement); + return; + } + + widget_id = (char *)sqlite3_column_text(p_statement, 0); + instance_id = (char *)sqlite3_column_text(p_statement, 1); + status = sqlite3_column_int(p_statement, 2); + + cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, "NULL"); + if (cb_info) + cb_info->cb(widget_id, instance_id, status, cb_info->data); + + cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id); + if (cb_info) + cb_info->cb(widget_id, instance_id, status, cb_info->data); + + ret = sqlite3_finalize(p_statement); + if (ret != SQLITE_OK) + _E("sqlite3 error [%d] : <%s> finalize", ret, sqlite3_errmsg(_widget_db)); + + return; +} + +/* within package only */ +EAPI int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, int status, void *data), void *data) +{ + struct lifecycle_local_s *cb_info; + + if (!widget_id) + widget_id = "NULL"; /* listen all widget */ + + cb_info = (struct lifecycle_local_s *)malloc(sizeof(struct lifecycle_local_s)); + if (!cb_info) { + _E("out of memory"); + return -1; + } + + cb_info->widget_id = strdup(widget_id); + cb_info->cb = cb; + cb_info->data = data; + if (!lifecycle_tbl) { + lifecycle_tbl = g_hash_table_new(g_str_hash, g_str_equal); + if (!lifecycle_tbl) { + free(cb_info); + return -1; + } + } + + g_hash_table_insert(lifecycle_tbl, cb_info->widget_id, cb_info); + + if (!is_update_hook_registered) { + if (!__init(true)) { + sqlite3_update_hook(_widget_db, __update_cb, NULL); + is_update_hook_registered = 1; + } else { + _E("failed to register update hook"); + } + } + + return 0; +} + +EAPI int widget_instance_unlisten_status(const char *widget_id) +{ + struct lifecycle_local_s *cb_info; + + if (!widget_id) + widget_id = "NULL"; + + cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id); + if (!cb_info) + return -1; + + g_hash_table_remove(lifecycle_tbl, widget_id); + free(cb_info->widget_id); + free(cb_info); + return 0; +} diff --git a/src/widget_service.c b/src/widget_service.c index 31b56d9..60681a6 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -37,6 +37,8 @@ #define MAX_BUF_SIZE 4096 +static GList *lifecycle_cbs; + static inline bool _is_widget_feature_enabled(void) { static bool feature = false; @@ -1329,9 +1331,28 @@ EAPI int widget_service_get_widget_instance_list(const char *widget_id, widget_i return ret < 0 ? (ret == -2 ? WIDGET_ERROR_PERMISSION_DENIED : WIDGET_ERROR_NOT_EXIST) : WIDGET_ERROR_NONE; } +struct lifecycle_s { + char *widget_id; + widget_lifecycle_event_cb cb; + void *data; +}; + +static int __listen_status(const char *widget_id, const char *instance_id, int status, void *data) +{ + struct lifecycle_s *cb_info = (struct lifecycle_s *)data; + if (!cb_info) + return 0; + + cb_info->cb(widget_id, status, instance_id, data); + + return 0; +} + EAPI int widget_service_set_lifecycle_event_cb(const char *widget_id, widget_lifecycle_event_cb cb, void *data) { int ret = WIDGET_ERROR_NONE; + struct lifecycle_s *cb_info; + GList *head = lifecycle_cbs; if (!_is_widget_feature_enabled()) { _E("not supported"); @@ -1343,20 +1364,79 @@ EAPI int widget_service_set_lifecycle_event_cb(const char *widget_id, widget_lif return WIDGET_ERROR_INVALID_PARAMETER; } - /* TODO */ + while (head) { + cb_info = (struct lifecycle_s *)head->data; + if (cb_info && widget_id && cb_info->widget_id) { + if (strncmp(cb_info->widget_id, widget_id, strlen(widget_id)) == 0) + return WIDGET_ERROR_INVALID_PARAMETER; + + } else if (cb_info && widget_id == NULL && cb_info->widget_id == NULL) { + return WIDGET_ERROR_INVALID_PARAMETER; + } + + head = head->next; + } + + cb_info = (struct lifecycle_s *)malloc(sizeof(struct lifecycle_s)); + if (cb_info == NULL) + return WIDGET_ERROR_OUT_OF_MEMORY; + + if (widget_id) + cb_info->widget_id = strdup(widget_id); + else + cb_info->widget_id = NULL; + + cb_info->cb = cb; + cb_info->data = data; + + lifecycle_cbs = g_list_append(lifecycle_cbs, cb_info); + + widget_instance_listen_status(widget_id, __listen_status, cb_info); return ret; } EAPI int widget_service_unset_lifecycle_event_cb(const char *widget_id, void **user_data) { - int ret = WIDGET_ERROR_NONE; + struct lifecycle_s *cb_info; + struct lifecycle_s *found = NULL; + GList *head = lifecycle_cbs; if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } - /* TODO */ - return ret; + while (head) { + cb_info = (struct lifecycle_s *)head->data; + if (cb_info && widget_id && cb_info->widget_id) { + if (strncmp(cb_info->widget_id, widget_id, strlen(widget_id)) == 0) { + found = cb_info; + break; + } + } else if (cb_info && widget_id == NULL && cb_info->widget_id == NULL) { + found = cb_info; + break; + } + + head = head->next; + } + + if (found) { + lifecycle_cbs = g_list_remove(lifecycle_cbs, found); + if (user_data) + *user_data = found->data; + + if (found->widget_id) + free(found->widget_id); + + free(found); + + widget_instance_unlisten_status(widget_id); + + return WIDGET_ERROR_NONE; + } + + return WIDGET_ERROR_NOT_EXIST; } + -- 2.7.4 From 8de1418f50f98e61668b0154a4d386b60bae45a9 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Thu, 24 Mar 2016 23:15:39 +0900 Subject: [PATCH 08/16] Add pirivilege check Change-Id: I9d55acde45eb02a9568e7ed3997d9bcface3abaa --- CMakeLists.txt | 1 + packaging/libwidget_service.spec | 1 + src/widget_service.c | 59 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ff419b..215c621 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ pkg_check_modules(pkgs REQUIRED aul libtzplatform-config uuid + cynara-client ) FOREACH(flag ${pkgs_CFLAGS}) diff --git a/packaging/libwidget_service.spec b/packaging/libwidget_service.spec index aaf5bf5..43c30f8 100644 --- a/packaging/libwidget_service.spec +++ b/packaging/libwidget_service.spec @@ -24,6 +24,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(cynara-client) %if "%{model_build_feature_widget}" == "0" ExclusiveArch: diff --git a/src/widget_service.c b/src/widget_service.c index 60681a6..3897bee 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include "widget_errno.h" #include "debug.h" @@ -36,6 +39,7 @@ #include "widget_service.h" #define MAX_BUF_SIZE 4096 +#define SMACK_LABEL_LEN 255 static GList *lifecycle_cbs; @@ -60,6 +64,58 @@ static inline bool _is_widget_feature_enabled(void) return feature; } +static int check_privilege(const char *privilege) +{ + cynara *p_cynara; + + int fd = 0; + int ret = 0; + + char subject_label[SMACK_LABEL_LEN + 1] = ""; + char uid[10] = {0,}; + char *client_session = ""; + + ret = cynara_initialize(&p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + LOGE("cannot init cynara [%d] failed!", ret); + ret = -1; + goto out; + } + + fd = open("/proc/self/attr/current", O_RDONLY); + if (fd < 0) { + LOGE("open [%d] failed!", errno); + ret = -1; + goto out; + } + + ret = read(fd, subject_label, SMACK_LABEL_LEN); + if (ret < 0) { + LOGE("read [%d] failed!", errno); + close(fd); + ret = -1; + goto out; + } + close(fd); + + snprintf(uid, 10, "%d", getuid()); + + ret = cynara_check(p_cynara, subject_label, client_session, uid, + privilege); + if (ret != CYNARA_API_ACCESS_ALLOWED) { + LOGE("cynara access check [%d] failed!", ret); + ret = -1; + goto out; + } + + ret = 0; +out: + if (p_cynara) + cynara_finish(p_cynara); + + return ret; +} + #define ROOT_USER 0 #define GLOBALAPP_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) static int _is_global(uid_t uid) @@ -423,6 +479,9 @@ EAPI int widget_service_get_widget_list(widget_list_cb cb, void *data) return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + ret = _get_widget_list(NULL, getuid(), &list); if (ret == WIDGET_ERROR_NONE) ret = _get_widget_list(NULL, GLOBALAPP_USER, &list); -- 2.7.4 From f30be40feab36fabed385d8e009b3672366e4551 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 28 Mar 2016 14:40:49 +0900 Subject: [PATCH 09/16] Fix doxygen comments Change-Id: Id0e9f04028573c24ab912946a24ca3fc6c34cf8d Signed-off-by: Hwankyu Jhun --- include/widget_service_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/widget_service_internal.h b/include/widget_service_internal.h index 30ab9fa..38e15e5 100644 --- a/include/widget_service_internal.h +++ b/include/widget_service_internal.h @@ -750,7 +750,7 @@ extern int widget_service_get_widget_max_count(const char *widget_id); /** * @brief Getting the auto_align option - * @since_tizen 2.4 + * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif * @param[in] widget_id widget application id * @return state of auto_align mode. 1 if it is turned on or 0 if it is turned off. otherwise a negative error value * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid parameter -- 2.7.4 From e29b230fcd59f77958387e6489b5a8222deac772 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Wed, 30 Mar 2016 20:05:57 +0900 Subject: [PATCH 10/16] Fix no endpoint provided for widget instance Change-Id: Ibe1c01e2f98cfbf82667eac90d21a2d8bc206966 Signed-off-by: Daehyeon Jung --- src/widget_instance.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widget_instance.c b/src/widget_instance.c index 12b188e..83d555d 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -620,6 +620,7 @@ EAPI int widget_instance_launch(const char *widget_id, const char *instance_id, snprintf(pid_buf, sizeof(pid_buf), "%d", getpid()); bundle_add_str(b, WIDGET_K_CALLER, pid_buf); + bundle_add_str(b, WIDGET_K_ENDPOINT, viewer_appid); 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"); @@ -724,6 +725,8 @@ static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundl return 0; } + _D("update status %s on %d", instance_id, *status); + instance = __pick_instance(widget_id, instance_id); if (instance == NULL) { -- 2.7.4 From 01221072b99c2dea9679956214f22500db5985eb Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Fri, 8 Apr 2016 16:55:12 +0900 Subject: [PATCH 11/16] fix misuage of g_strdup, fix update instance Change-Id: I04aedb4027455e5f10f32da5a4c66f565f7eee14 --- src/widget_instance.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/widget_instance.c b/src/widget_instance.c index 83d555d..3f92d2e 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -205,8 +205,8 @@ static struct widget_app *__add_app(const char *widget_id, const char *viewer_id return NULL; } - app->viewer_id = g_strdup(viewer_id); - app->widget_id = g_strdup(widget_id); + app->viewer_id = strdup(viewer_id); + app->widget_id = strdup(widget_id); app->instances = NULL; _widget_apps = g_list_append(_widget_apps, app); @@ -214,7 +214,7 @@ static struct widget_app *__add_app(const char *widget_id, const char *viewer_id return app; } -static const char *__create_instance_id(const char *widget_id) +static char *__create_instance_id(const char *widget_id) { char uuid[37]; char instance_id[MAX_INSTANCE_ID_LEN]; @@ -239,7 +239,7 @@ static const char *__create_instance_id(const char *widget_id) _D("new instance: %s", instance_id); - return g_strdup(instance_id); + return strdup(instance_id); } static struct _widget_instance *__add_instance(const char *id, const char *widget_id) @@ -254,10 +254,10 @@ static struct _widget_instance *__add_instance(const char *id, const char *widge } instance->status = WIDGET_INSTANCE_CREATED; - instance->id = (char *)id; + instance->id = strdup(id); instance->pid = 0; instance->stored = 0; - instance->widget_id = g_strdup(widget_id); + instance->widget_id = strdup(widget_id); instance->content_info = NULL; instance->ref = 0; @@ -341,6 +341,7 @@ static int __load_instance_list() 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); @@ -361,6 +362,8 @@ static int __load_instance_list() continue; } + _D("added %s, %d", instance_id, content_info); + 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); @@ -381,7 +384,7 @@ 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, status) VALUES(?,?,?,?,?)"; - const char update_query[] = "UPDATE widget_instance SET content_info=? status=? WHERE instance_id=?"; + const char update_query[] = "UPDATE widget_instance SET content_info=?, status=? WHERE instance_id=?"; const char delete_query[] = "DELETE FROM widget_instance WHERE instance_id=?"; sqlite3_stmt* p_statement; struct widget_app *app = NULL; @@ -405,7 +408,7 @@ static int __update_instance_info(struct _widget_instance *instance) } if (content == NULL) { - content = g_strdup("NULL"); + content = strdup("NULL"); content_len = strlen("NULL"); } @@ -491,7 +494,7 @@ cleanup: EAPI int widget_instance_create(const char *widget_id, char **instance_id) { - const char *id = NULL; + char *id = NULL; struct _widget_instance *instance = NULL; _D("create: %s", widget_id); @@ -504,8 +507,10 @@ EAPI int widget_instance_create(const char *widget_id, char **instance_id) instance = __add_instance(id, widget_id); + free((gpointer)id); + if (instance) { - *instance_id = (char *)id; + *instance_id = instance->id; _D("create done"); return 0; } @@ -781,7 +786,7 @@ EAPI int widget_instance_init(const char *viewer_id) if (viewer_id == NULL) return -1; - viewer_appid = g_strdup(viewer_id); + viewer_appid = strdup(viewer_id); __init(false); __load_instance_list(); @@ -805,7 +810,7 @@ EAPI int widget_instance_fini() __fini(); if (viewer_appid) { - g_free(viewer_appid); + free(viewer_appid); viewer_appid = NULL; } @@ -996,6 +1001,8 @@ static void __update_cb(void *data, int action, char const *db_name, char const int status; struct lifecycle_local_s *cb_info; + _D("update cb"); + buf = sqlite3_mprintf("SELECT widget_id, instance_id, status FROM widget_instance WHERE rowid='%lld';", rowid); if (buf == NULL) return; -- 2.7.4 From 2759e65b257df0ab4947874986e69f5f8f70db34 Mon Sep 17 00:00:00 2001 From: "seungha.son" Date: Thu, 14 Apr 2016 09:23:02 +0900 Subject: [PATCH 12/16] fix coding style Change-Id: I4650f537e6ecd46e79c588c137aafc6298166e01 Signed-off-by: seungha.son --- tool/widget_test.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tool/widget_test.c b/tool/widget_test.c index fe4d8ee..f4c85a3 100644 --- a/tool/widget_test.c +++ b/tool/widget_test.c @@ -34,9 +34,8 @@ static void print_usage(char *pname) printf("[usage] %s ...\n", pname); printf(" - available cmd list \n"); - for (i = 0; i < sizeof(test_func) / sizeof(test_func_t); i++) { + for (i = 0; i < sizeof(test_func) / sizeof(test_func_t); i++) printf("%s %s %s\n\n", pname, test_func[i].cmd, test_func[i].usage); - } printf(" - end cmd list\n"); } @@ -50,9 +49,8 @@ int main(int argc, char **argv) } for (i = 0; i < (sizeof(test_func) / sizeof(test_func_t)); i++) { - if (strcmp(test_func[i].cmd, argv[1]) == 0) { + if (strcmp(test_func[i].cmd, argv[1]) == 0) return test_func[i].fn(argc, argv); - } } print_usage(argv[0]); -- 2.7.4 From 63c72ded03930698e14fb395f0fbcb7433134bf1 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Tue, 19 Apr 2016 17:05:15 +0900 Subject: [PATCH 13/16] Add widget operation to pass privilege check Change-Id: Idfddd69b4ba80e745ceedf98942f9e0340b7e147 Signed-off-by: Daehyeon Jung --- src/widget_instance.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widget_instance.c b/src/widget_instance.c index 3f92d2e..811de83 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -542,6 +542,7 @@ static int __send_aul_cmd(const char *widget_id, const char *instance_id, bundle bundle_add_str(b, WIDGET_K_CLASS, classid); aul_svc_set_loader_id(b, 1); + aul_svc_set_operation(b, AUL_SVC_OPERATION_LAUNCH_WIDGET); ret = aul_launch_app(appid, b); -- 2.7.4 From 76d964b5e90cf435a0b78618305aed0542013216 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Wed, 27 Apr 2016 19:36:33 +0900 Subject: [PATCH 14/16] check privilege Change-Id: I6ebc7ed6d112560c50528ec21b6c8701d2223a11 Signed-off-by: Daehyeon Jung --- src/widget_service.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/widget_service.c b/src/widget_service.c index 3897bee..77be756 100644 --- a/src/widget_service.c +++ b/src/widget_service.c @@ -518,6 +518,9 @@ EAPI int widget_service_get_widget_list_by_pkgid(const char *pkgid, return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + ret = _get_widget_list(pkgid, getuid(), &list); if (ret == WIDGET_ERROR_NONE) ret = _get_widget_list(pkgid, GLOBALAPP_USER, &list); @@ -619,6 +622,11 @@ EAPI char *widget_service_get_main_app_id(const char *widget_id) return NULL; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return NULL; + } + appid = _get_main_app_id(widget_id, getuid()); if (appid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) appid = _get_main_app_id(widget_id, GLOBALAPP_USER); @@ -645,6 +653,11 @@ EAPI int widget_service_get_supported_size_types(const char *widget_id, return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + + _D("id : %s", widget_id); + ret = _get_widget_supported_sizes(widget_id, getuid(), cnt, &width, &height); if (ret == WIDGET_ERROR_NOT_EXIST) @@ -746,6 +759,12 @@ EAPI char *widget_service_get_app_id_of_setup_app(const char *widget_id) return NULL; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + _E("permission denied"); + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return NULL; + } + appid = _get_app_id_of_setup_app(widget_id, getuid()); if (appid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) appid = _get_app_id_of_setup_app(widget_id, GLOBALAPP_USER); @@ -815,6 +834,12 @@ EAPI int widget_service_get_nodisplay(const char *widget_id) return 0; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + _E("permission denied"); + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return 0; + } + nodisplay = _get_nodisplay(widget_id, getuid()); if (get_last_result() == WIDGET_ERROR_NOT_EXIST) nodisplay = _get_nodisplay(widget_id, GLOBALAPP_USER); @@ -835,6 +860,9 @@ EAPI int widget_service_get_need_of_frame(const char *pkgid, widget_size_type_e return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + *need_of_frame = false; return WIDGET_ERROR_NONE; @@ -853,6 +881,9 @@ EAPI int widget_service_get_need_of_touch_effect(const char *pkgid, widget_size_ return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + *need_of_touch_event = false; return WIDGET_ERROR_NONE; @@ -871,6 +902,9 @@ EAPI int widget_service_get_need_of_mouse_event(const char *pkgid, widget_size_t return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + *need_of_mouse_event = false; return WIDGET_ERROR_NONE; } @@ -947,6 +981,11 @@ EAPI char *widget_service_get_preview_image_path(const char *widget_id, return NULL; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return NULL; + } + if (_get_supported_size(size_type, &width, &height)) { set_last_result(WIDGET_ERROR_NOT_SUPPORTED); return NULL; @@ -1035,6 +1074,11 @@ EAPI char *widget_service_get_icon(const char *widget_id, const char *lang) return NULL; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return NULL; + } + icon = _get_icon(widget_id, lang, getuid()); if (icon == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) icon = _get_icon(widget_id, lang, GLOBALAPP_USER); @@ -1114,6 +1158,12 @@ EAPI char *widget_service_get_name(const char *widget_id, const char *lang) set_last_result(WIDGET_ERROR_INVALID_PARAMETER); return NULL; } + + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { + set_last_result(WIDGET_ERROR_PERMISSION_DENIED); + return NULL; + } + name = _get_name(widget_id, lang, getuid()); if (name == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST) name = _get_name(widget_id, lang, GLOBALAPP_USER); @@ -1136,6 +1186,9 @@ EAPI int widget_service_get_supported_sizes(const char *widget_id, int *cnt, return WIDGET_ERROR_INVALID_PARAMETER; } + if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) + return WIDGET_ERROR_PERMISSION_DENIED; + ret = _get_widget_supported_sizes(widget_id, getuid(), cnt, w, h); if (ret == WIDGET_ERROR_NOT_EXIST) ret = _get_widget_supported_sizes(widget_id, GLOBALAPP_USER, -- 2.7.4 From 8097d51fbb8c06b0423dad3d5c2b697c9dd412a3 Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Tue, 10 May 2016 12:16:17 +0900 Subject: [PATCH 15/16] Add widget event notify - lifecycle event notify replaced to aul_app_com (permission handling NYI) - added most widget events for widget viewer Change-Id: I1a7fef0f868a298eefbc931db4e7f0694dbdb179 Signed-off-by: Daehyeon Jung --- include/widget_instance.h | 17 +++- src/widget_instance.c | 255 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 206 insertions(+), 66 deletions(-) diff --git a/include/widget_instance.h b/include/widget_instance.h index 6a468ff..03fde8b 100644 --- a/include/widget_instance.h +++ b/include/widget_instance.h @@ -19,6 +19,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +37,7 @@ extern "C" { #define WIDGET_K_HEIGHT "__WIDGET_HEIGHT__" #define WIDGET_K_REASON "__WIDGET_REASON__" #define WIDGET_K_PERIOD "__WIDGET_PERIOD__" +#define WIDGET_K_FORCE "__WIDGET_FORCE__" typedef enum widget_instance_event { WIDGET_INSTANCE_EVENT_CREATE = 0, @@ -46,10 +48,12 @@ typedef enum widget_instance_event { WIDGET_INSTANCE_EVENT_UPDATE = 5, WIDGET_INSTANCE_EVENT_PERIOD_CHANGED = 6, WIDGET_INSTANCE_EVENT_SIZE_CHANGED = 7, + WIDGET_INSTANCE_EVENT_EXTRA_UPDATED = 8, + WIDGET_INSTANCE_EVENT_FAULT = 9, WIDGET_INSTANCE_EVENT_MAX, } widget_instance_event_e; -typedef struct _widget_instance* widget_instance_h; +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); @@ -63,16 +67,23 @@ 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_resume(const char *widget_id, const char *instance_id); +int widget_instance_pause(const char *widget_id, const char *instance_id); +int widget_instance_resize(const char *widget_id, const char *instance_id, int w, int h); int widget_instance_init(const char *viewer_id); int widget_instance_fini(); +typedef int (*widget_instance_event_cb)(const char *widget_id, const char *instance_id, int event, void *data); + widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id); -int widget_instance_get_instance_list(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, void *data), void *data); +int widget_instance_get_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data); void widget_instance_unref(widget_instance_h instance); widget_instance_h widget_instance_ref(widget_instance_h instance); int widget_instance_change_period(widget_instance_h instance, double period); int widget_instance_trigger_update(widget_instance_h instance, bundle *b, int force); -int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, int status, void *data), void *data); +int widget_instance_listen_event(widget_instance_event_cb cb, void *data); +int widget_instance_unlisten_event(widget_instance_event_cb cb); +int widget_instance_listen_status(const char *widget_id, widget_instance_event_cb cb, void *data); int widget_instance_unlisten_status(const char *widget_id); #ifdef __cplusplus diff --git a/src/widget_instance.c b/src/widget_instance.c index 811de83..bd7f764 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -76,14 +76,21 @@ static GList *_widget_apps = NULL; static sqlite3 *_widget_db = NULL; static char *viewer_appid = NULL; -static aul_app_com_connection_h conn = NULL; +static aul_app_com_connection_h conn_viewer; +static aul_app_com_connection_h conn_status; static GHashTable *lifecycle_tbl; -static int is_update_hook_registered; +static int is_status_handler_connected; struct lifecycle_local_s { char *widget_id; - int (*cb)(const char *, const char *, int, void *); + widget_instance_event_cb cb; + void *data; +}; + +static GList *event_cbs; +struct event_cb_s { + widget_instance_event_cb cb; void *data; }; @@ -100,20 +107,13 @@ static int __init(bool readonly) { int rc; char db_path[TIZEN_PATH_MAX]; - char *app_path = NULL; if (_widget_db) { _D("already initialized"); return 0; } - app_path = app_get_data_path(); - if (!app_path) { - _D("failed to get app path"); - return 0; - } - - snprintf(db_path, sizeof(db_path), "%s/%s", app_path, ".widget_instance.db"); + snprintf(db_path, sizeof(db_path), "%s/%d/%s", "/run/user/", getuid(), ".widget_instance.db"); rc = sqlite3_open_v2(db_path, &_widget_db, readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); @@ -264,6 +264,9 @@ static struct _widget_instance *__add_instance(const char *id, const char *widge _widget_instances = g_list_append(_widget_instances, instance); app = __pick_app(widget_id); + if (!app) + app = __add_app(widget_id, viewer_appid); + if (app) app->instances = g_list_append(app->instances, instance); else @@ -323,7 +326,7 @@ static int __load_instance_list() struct _widget_instance *instance = NULL; struct widget_app *app = NULL; - sqlite3_stmt* p_statement; + sqlite3_stmt *p_statement; if (_widget_db == NULL) { _E("widget db is not initialized"); @@ -614,6 +617,10 @@ EAPI int widget_instance_launch(const char *widget_id, const char *instance_id, _E("failed to create instance for %s", widget_id); return -1; } + } else { + if (__pick_instance(widget_id, instance) == NULL) { + __add_instance(instance, widget_id); + } } if (b == NULL) { @@ -682,6 +689,60 @@ EAPI int widget_instance_destroy(const char *widget_id, const char *instance_id) return ret; } +EAPI int widget_instance_resume(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, "resume"); + + ret = __send_aul_cmd(widget_id, instance_id, b); + + bundle_free(b); + + return ret; +} + +EAPI int widget_instance_pause(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, "pause"); + + ret = __send_aul_cmd(widget_id, instance_id, b); + + bundle_free(b); + + return ret; +} + +EAPI int widget_instance_resize(const char *widget_id, const char *instance_id, int w, int h) +{ + 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, "resize"); + + __set_width(b, w); + __set_height(b, h); + + 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; @@ -710,6 +771,66 @@ EAPI int widget_instance_foreach(const char *widget_id, widget_instance_foreach_ return 0; } +static void __notify_event(int event, const char *widget_id, const char *instance_id) +{ + struct event_cb_s *cb_info; + GList *iter = event_cbs; + + while (iter) { + cb_info = (struct event_cb_s *)iter->data; + if (cb_info && cb_info->cb) + cb_info->cb(widget_id, instance_id, event, cb_info->data); + + iter = iter->next; + } +} + +static int __status_handler(const char *endpoint, aul_app_com_result_e e, bundle *envelope, void *user_data) +{ + char *widget_id; + char *instance_id; + int *status; + size_t status_sz = 0; + struct lifecycle_local_s *cb_info; + + bundle_get_str(envelope, WIDGET_K_ID, &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("status: %d", *status); + + return 0; + } + + cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, "NULL"); + if (cb_info) + cb_info->cb(widget_id, instance_id, *status, cb_info->data); + + cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id); + if (cb_info) + cb_info->cb(widget_id, instance_id, *status, cb_info->data); + + return 0; +} + +static int __connect_status_handler() +{ + if (is_status_handler_connected) + return 0; + + if (aul_app_com_create("widget.status", NULL, __status_handler, NULL, &conn_status) < 0) { + _E("failed to create status"); + return -1; + } + + is_status_handler_connected = 1; + + 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; @@ -719,7 +840,7 @@ static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundl int cmd = 0; struct _widget_instance *instance; - bundle_get_str(envelope, WIDGET_K_CLASS, &widget_id); + bundle_get_str(envelope, WIDGET_K_ID, &widget_id); bundle_get_str(envelope, WIDGET_K_INSTANCE, &instance_id); bundle_get_byte(envelope, WIDGET_K_STATUS, (void **)&status, &status_sz); @@ -768,17 +889,24 @@ static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundl instance->status = WIDGET_INSTANCE_RUNNING; break; case WIDGET_INSTANCE_EVENT_UPDATE: + break; + case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED: if (instance->content_info) bundle_free(instance->content_info); instance->content_info = bundle_dup(envelope); __update_instance_info(instance); break; + case WIDGET_INSTANCE_EVENT_FAULT: + + break; default: _E("unknown command: %d", cmd); break; } + __notify_event(cmd, widget_id, instance_id); + return 0; } @@ -788,11 +916,12 @@ EAPI int widget_instance_init(const char *viewer_id) return -1; viewer_appid = strdup(viewer_id); - __init(false); + __init(false); __load_instance_list(); + __connect_status_handler(); - if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn) < 0) { + if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn_viewer) < 0) { _E("failed to create app com endpoint"); return -1; } @@ -803,9 +932,14 @@ EAPI int widget_instance_init(const char *viewer_id) EAPI int widget_instance_fini() { - if (conn) { - if (aul_app_com_leave(conn) < 0) - _E("failed to leave app com endpoint"); + if (conn_viewer) { + if (aul_app_com_leave(conn_viewer) < 0) + _E("failed to leave app com endpoint viewer"); + } + + if (conn_status) { + if (aul_app_com_leave(conn_status) < 0) + _E("failed to leave app com endpoint status"); } __fini(); @@ -912,6 +1046,9 @@ EAPI int widget_instance_trigger_update(widget_instance_h instance, bundle *b, i bundle_add_str(kb, WIDGET_K_OPERATION, "update"); + if (force) + bundle_add_str(kb, WIDGET_K_FORCE, "true"); + ret = __send_aul_cmd(instance->widget_id, instance->id, kb); if (!b) @@ -992,56 +1129,55 @@ EAPI widget_instance_h widget_instance_ref(widget_instance_h instance) return instance; } -static void __update_cb(void *data, int action, char const *db_name, char const *table_name, sqlite_int64 rowid) +EAPI int widget_instance_listen_event(widget_instance_event_cb cb, void *data) { - char *buf; - int ret; - sqlite3_stmt* p_statement; - char *widget_id; - char *instance_id; - int status; - struct lifecycle_local_s *cb_info; - - _D("update cb"); - - buf = sqlite3_mprintf("SELECT widget_id, instance_id, status FROM widget_instance WHERE rowid='%lld';", rowid); - if (buf == NULL) - return; + struct event_cb_s *cb_info; - ret = sqlite3_prepare_v2(_widget_db, buf, strlen(buf), &p_statement, NULL); - if (ret != SQLITE_OK) { - _E("sqlite3 error [%d] : <%s> executing statement\n", ret, sqlite3_errmsg(_widget_db)); - return; + cb_info = (struct event_cb_s *)malloc(sizeof(struct event_cb_s)); + if (!cb_info) { + _E("out of memory"); + return -1; } - ret = sqlite3_step(p_statement); - if (ret != SQLITE_ROW) { - _E("step error: %s", sqlite3_errmsg(_widget_db)); - sqlite3_finalize(p_statement); - return; + cb_info->cb = cb; + cb_info->data = data; + + event_cbs = g_list_append(event_cbs, cb_info); + if (!event_cbs) { + _E("out of memory"); + return -1; } - widget_id = (char *)sqlite3_column_text(p_statement, 0); - instance_id = (char *)sqlite3_column_text(p_statement, 1); - status = sqlite3_column_int(p_statement, 2); + return 0; +} - cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, "NULL"); - if (cb_info) - cb_info->cb(widget_id, instance_id, status, cb_info->data); +EAPI int widget_instance_unlisten_event(widget_instance_event_cb cb) +{ + struct event_cb_s *cb_info; + GList *iter = event_cbs; - cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id); - if (cb_info) - cb_info->cb(widget_id, instance_id, status, cb_info->data); + if (!cb) { + _E("invalid parameter"); + return -1; + } - ret = sqlite3_finalize(p_statement); - if (ret != SQLITE_OK) - _E("sqlite3 error [%d] : <%s> finalize", ret, sqlite3_errmsg(_widget_db)); + while (iter) { + cb_info = (struct event_cb_s *)iter->data; + if (cb_info && cb_info->cb == cb) { + event_cbs = g_list_remove_link(event_cbs, iter); + free(cb_info); + g_list_free(iter); + return 0; + } + iter = iter->next; + } - return; + _E("wrong argument"); + return -1; } /* within package only */ -EAPI int widget_instance_listen_status(const char *widget_id, int (*cb)(const char *widget_id, const char *instance_id, int status, void *data), void *data) +EAPI int widget_instance_listen_status(const char *widget_id, widget_instance_event_cb cb, void *data) { struct lifecycle_local_s *cb_info; @@ -1067,14 +1203,7 @@ EAPI int widget_instance_listen_status(const char *widget_id, int (*cb)(const ch g_hash_table_insert(lifecycle_tbl, cb_info->widget_id, cb_info); - if (!is_update_hook_registered) { - if (!__init(true)) { - sqlite3_update_hook(_widget_db, __update_cb, NULL); - is_update_hook_registered = 1; - } else { - _E("failed to register update hook"); - } - } + __connect_status_handler(); return 0; } -- 2.7.4 From 87d9b1a3a4b4e57d321ab08e27adfebbadd87ecb Mon Sep 17 00:00:00 2001 From: Daehyeon Jung Date: Tue, 17 May 2016 21:12:53 +0900 Subject: [PATCH 16/16] Add fault handler - In widget crash, notify WIDGET_INSTANCE_EVENT_FAULT to instance handler - Fix some possible memory leaks Change-Id: Ic4f7798724ef5463c2d4a445772a9efba0f5689b Signed-off-by: Daehyeon Jung --- src/widget_instance.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/widget_instance.c b/src/widget_instance.c index bd7f764..787b25a 100644 --- a/src/widget_instance.c +++ b/src/widget_instance.c @@ -658,9 +658,13 @@ EAPI int widget_instance_launch(const char *widget_id, const char *instance_id, EAPI int widget_instance_terminate(const char *widget_id, const char *instance_id) { int ret = 0; - bundle *b = bundle_create(); + bundle *b = NULL; - if (widget_id == NULL || instance_id == NULL || b == NULL) + if (widget_id == NULL || instance_id == NULL) + return -1; + + b = bundle_create(); + if (b == NULL) return -1; bundle_add_str(b, WIDGET_K_OPERATION, "terminate"); @@ -675,9 +679,13 @@ EAPI int widget_instance_terminate(const char *widget_id, const char *instance_i EAPI int widget_instance_destroy(const char *widget_id, const char *instance_id) { int ret = 0; - bundle *b = bundle_create(); + bundle *b = NULL; - if (widget_id == NULL || instance_id == NULL || b == NULL) + if (widget_id == NULL || instance_id == NULL) + return -1; + + b = bundle_create(); + if (b == NULL) return -1; bundle_add_str(b, WIDGET_K_OPERATION, "destroy"); @@ -692,9 +700,13 @@ EAPI int widget_instance_destroy(const char *widget_id, const char *instance_id) EAPI int widget_instance_resume(const char *widget_id, const char *instance_id) { int ret = 0; - bundle *b = bundle_create(); + bundle *b = NULL; - if (widget_id == NULL || instance_id == NULL || b == NULL) + if (widget_id == NULL || instance_id == NULL) + return -1; + + b = bundle_create(); + if (b == NULL) return -1; bundle_add_str(b, WIDGET_K_OPERATION, "resume"); @@ -709,9 +721,13 @@ EAPI int widget_instance_resume(const char *widget_id, const char *instance_id) EAPI int widget_instance_pause(const char *widget_id, const char *instance_id) { int ret = 0; - bundle *b = bundle_create(); + bundle *b = NULL; - if (widget_id == NULL || instance_id == NULL || b == NULL) + if (widget_id == NULL || instance_id == NULL) + return -1; + + b = bundle_create(); + if (b == NULL) return -1; bundle_add_str(b, WIDGET_K_OPERATION, "pause"); @@ -726,9 +742,13 @@ EAPI int widget_instance_pause(const char *widget_id, const char *instance_id) EAPI int widget_instance_resize(const char *widget_id, const char *instance_id, int w, int h) { int ret = 0; - bundle *b = bundle_create(); + bundle *b = NULL; - if (widget_id == NULL || instance_id == NULL || b == NULL) + if (widget_id == NULL || instance_id == NULL) + return -1; + + b = bundle_create(); + if (b == NULL) return -1; bundle_add_str(b, WIDGET_K_OPERATION, "resize"); @@ -910,6 +930,27 @@ static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundl return 0; } +static int __fault_handler(int pid, void *data) +{ + GList *iter; + struct _widget_instance *instance; + + iter = _widget_instances; + + while (iter) { + instance = (struct _widget_instance *)iter->data; + if (instance && instance->pid == pid) { + instance->pid = 0; + instance->status = WIDGET_INSTANCE_TERMINATED; + __update_instance_info(instance); + __notify_event(WIDGET_INSTANCE_EVENT_FAULT, instance->widget_id, instance->id); + } + iter = iter->next; + } + + return 0; +} + EAPI int widget_instance_init(const char *viewer_id) { if (viewer_id == NULL) @@ -920,6 +961,7 @@ EAPI int widget_instance_init(const char *viewer_id) __init(false); __load_instance_list(); __connect_status_handler(); + aul_listen_app_dead_signal(__fault_handler, NULL); if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn_viewer) < 0) { _E("failed to create app com endpoint"); -- 2.7.4