/* * Copyright 2013 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widget_errno.h" #include "debug.h" #include "widget_instance.h" #include "widget_service.h" #include "widget_service_internal.h" #define MAX_COLUMN 80 #define MAX_BUF_SIZE 4096 #define SMACK_LABEL_LEN 255 #define RESOLUTION_PATH_FORMAT "/usr/share/widget_service/%dx%d/resolution.ini" #define RESOLUTION_PATH_DEFAULT "/usr/share/widget_service/resolution.ini" #define RESOLUTION_SECTION_NAME "resolution" #define RESOLUTION_FORMAT "%dx%d" struct widget_instance_info_s { int period; bool exists; const char *instance_id; }; static GList *lifecycle_cbs; static bool _is_resolution_loaded = false; static const char *_iso3lang; static char _country[ULOC_COUNTRY_CAPACITY]; static char *_syslang; static inline bool _is_widget_feature_enabled(void) { static bool feature = false; static bool retrieved = false; int ret; if (retrieved == true) return feature; ret = system_info_get_platform_bool( "http://tizen.org/feature/shell.appwidget", &feature); if (ret != SYSTEM_INFO_ERROR_NONE) { _E("failed to get system info"); return false; } retrieved = true; return feature; } static int check_privilege(const char *privilege) { cynara *p_cynara = NULL; 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) { if (uid == ROOT_USER || uid == GLOBALAPP_USER) return 1; else return 0; } static const char *_get_db_path(uid_t uid) { const char *path; if (!_is_global(uid)) tzplatform_set_user(uid); path = tzplatform_mkpath(_is_global(uid) ? TZ_SYS_DB : TZ_USER_DB, ".widget.db"); tzplatform_reset_user(); return path; } static sqlite3 *_open_db(uid_t uid) { int ret; const char *path; sqlite3 *db; path = _get_db_path(uid); if (path == NULL) return NULL; ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("failed to open widget db: %d", ret); return NULL; /* LCOV_EXCL_STOP */ } return db; } static void _get_column_str(sqlite3_stmt *stmt, int idx, char **str) { char *val; val = (char *)sqlite3_column_text(stmt, idx); if (val) *str = strdup(val); else *str = NULL; } static void _get_column_int(sqlite3_stmt *stmt, int idx, int *i) { *i = sqlite3_column_int(stmt, idx); } static void _get_column_double(sqlite3_stmt *stmt, int idx, double *i) { *i = sqlite3_column_double(stmt, idx); } #define WIDGET_SIZE_TYPE_MAX 13 static int size_list[WIDGET_SIZE_TYPE_MAX][5] = { { 1, 1, 175, 175, WIDGET_SIZE_TYPE_1x1 }, /*!< 1x1 */ { 2, 1, 354, 175, WIDGET_SIZE_TYPE_2x1 }, /*!< 2x1 */ { 2, 2, 354, 354, WIDGET_SIZE_TYPE_2x2 }, /*!< 2x2 */ { 4, 1, 712, 175, WIDGET_SIZE_TYPE_4x1 }, /*!< 4x1 */ { 4, 2, 712, 354, WIDGET_SIZE_TYPE_4x2 }, /*!< 4x2 */ { 4, 3, 712, 533, WIDGET_SIZE_TYPE_4x3 }, /*!< 4x3 */ { 4, 4, 712, 712, WIDGET_SIZE_TYPE_4x4 }, /*!< 4x4 */ { 4, 5, 712, 891, WIDGET_SIZE_TYPE_4x5 }, /*!< 4x5 */ { 4, 6, 712, 1070, WIDGET_SIZE_TYPE_4x6 }, /*!< 4x6 */ { 21, 21, 224, 215, WIDGET_SIZE_TYPE_EASY_1x1 }, /*!< 21x21 */ { 23, 21, 680, 215, WIDGET_SIZE_TYPE_EASY_3x1 }, /*!< 23x21 */ { 23, 23, 680, 653, WIDGET_SIZE_TYPE_EASY_3x3 }, /*!< 23x23 */ { 0, 0, 720, 1280, WIDGET_SIZE_TYPE_FULL }, /*!< 0x0 */ }; static char *_resolution_file_path(void) { char *path; int length; int w, h; length = strlen(RESOLUTION_PATH_FORMAT) + 12; path = calloc(1, length); if (!path) { _E("calloc: %d\n", errno); return NULL; } ecore_wl_screen_size_get(&w, &h); _D("screen size : %d %d", w, h); snprintf(path, length, RESOLUTION_PATH_FORMAT, w, h); _D("Selected conf file: %s", path); if (access(path, F_OK) != 0) { _E("Fallback to default, access: %d", errno); strncpy(path, RESOLUTION_PATH_DEFAULT, length); if (access(path, F_OK) != 0) { _E("Serious error - there is no conf file, use default setting: %d\n", errno); free(path); path = NULL; } } return path; } static void _resolution_update_size_list(int width_type, int height_type, int width, int height) { int idx = 0; if (width_type == 1 && height_type == 1) { idx = 0; } else if (width_type == 2 && height_type == 1) { idx = 1; } else if (width_type == 2 && height_type == 2) { idx = 2; } else if (width_type == 4 && height_type == 1) { idx = 3; } else if (width_type == 4 && height_type == 2) { idx = 4; } else if (width_type == 4 && height_type == 3) { idx = 5; } else if (width_type == 4 && height_type == 4) { idx = 6; } else if (width_type == 4 && height_type == 5) { idx = 7; } else if (width_type == 4 && height_type == 6) { idx = 8; } else if (width_type == 21 && height_type == 21) { idx = 9; } else if (width_type == 23 && height_type == 21) { idx = 10; } else if (width_type == 23 && height_type == 23) { idx = 11; } else if (width_type == 0 && height_type == 0) { idx = 12; } else { _E("Unknown size type: %dx%d (%dx%d)\n", width_type, height_type, width, height); return; } size_list[idx][2] = width; size_list[idx][3] = height; } static int _resolution_update_from_file(void) { int width_type = 0; int height_type = 0; int width = 0; int height = 0; char *type_str; char *size_str; dictionary *dic; char *file_path = NULL; int key_num; char **key_list; char key_format[MAX_COLUMN]; int i; file_path = _resolution_file_path(); if (file_path == NULL) return WIDGET_ERROR_OUT_OF_MEMORY; dic = iniparser_load(file_path); if (dic == NULL) { _E("fail to load [%s] ", file_path); free(file_path); return WIDGET_ERROR_IO_ERROR; } free(file_path); snprintf(key_format, sizeof(key_format), "%s:%s", RESOLUTION_SECTION_NAME, RESOLUTION_FORMAT); key_num = iniparser_getsecnkeys(dic, RESOLUTION_SECTION_NAME); key_list = iniparser_getseckeys(dic, RESOLUTION_SECTION_NAME); for (i = 0; i < key_num; i++) { type_str = key_list[i]; size_str = iniparser_getstring(dic, type_str, NULL); if (sscanf(type_str, key_format, &width_type, &height_type) != 2) { _E("Invalid syntax: [%s]", type_str); continue; } if (sscanf(size_str, "%dx%d", &width, &height) != 2) { _E("Invalid syntax: [%s]", size_str); continue; } _resolution_update_size_list(width_type, height_type, width, height); } if (key_list) free(key_list); iniparser_freedict(dic); return WIDGET_ERROR_NONE; } static int _get_supported_size_type(int width, int height, int *type) { int i; if (!_is_resolution_loaded) { _resolution_update_from_file(); _is_resolution_loaded = true; } for (i = 0; i < WIDGET_SIZE_TYPE_MAX; i++) { if (width == size_list[i][2] && height == size_list[i][3]) break; } if (i == WIDGET_SIZE_TYPE_MAX) { _E("failed to get supported size"); return -1; } *type = size_list[i][4]; return 0; } static int _get_supported_size(int type, int *width, int *height) { int i; if (!_is_resolution_loaded) { _resolution_update_from_file(); _is_resolution_loaded = true; } for (i = 0; i < WIDGET_SIZE_TYPE_MAX; i++) { if (type == size_list[i][4]) break; } if (i == WIDGET_SIZE_TYPE_MAX) { _E("failed to get supported size type"); return -1; } *width = size_list[i][2]; *height = size_list[i][3]; return 0; } static int _convert_to_support_info(int *width, int *height, int *type, int count) { int i; int j; if (!_is_resolution_loaded) { _resolution_update_from_file(); _is_resolution_loaded = true; } for (j = 0; j < count; j++) { for (i = 0; i < WIDGET_SIZE_TYPE_MAX; i++) { if (size_list[i][0] == width[j] && size_list[i][1] == height[j]) break; } if (i == WIDGET_SIZE_TYPE_MAX) { _E("failed to get supported size type"); return -1; } width[j] = size_list[i][2]; height[j] = size_list[i][3]; type[j] = size_list[i][4]; } return 0; } static int _convert_to_support_size(int *width, int *height, int count) { int i; int j; if (!_is_resolution_loaded) { _resolution_update_from_file(); _is_resolution_loaded = true; } for (j = 0; j < count; j++) { for (i = 0; i < WIDGET_SIZE_TYPE_MAX; i++) { if (size_list[i][0] == width[j] && size_list[i][1] == height[j]) break; } if (i == WIDGET_SIZE_TYPE_MAX) { _E("failed to get supported size type"); return -1; } width[j] = size_list[i][2]; height[j] = size_list[i][3]; } return 0; } static int _convert_type_to_support_size_ratio(int type, int *w, int *h) { int i; if (!_is_resolution_loaded) { _resolution_update_from_file(); _is_resolution_loaded = true; } for (i = 0; i < WIDGET_SIZE_TYPE_MAX; i++) { if (size_list[i][4] == type) break; } if (i == WIDGET_SIZE_TYPE_MAX) { _E("failed to get support size ratio"); return -1; } *w = size_list[i][0]; *h = size_list[i][1]; return 0; } 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=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; int count = 0; int i; int *width; int *height; db = _open_db(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); while (sqlite3_step(stmt) == SQLITE_ROW) count++; if (count == 0) { sqlite3_finalize(stmt); sqlite3_close_v2(db); *cnt = 0; *w = NULL; *h = NULL; return WIDGET_ERROR_NOT_EXIST; } sqlite3_reset(stmt); width = malloc(sizeof(int) * count); height = malloc(sizeof(int) * count); for (i = 0; i < count; i++) { sqlite3_step(stmt); _get_column_int(stmt, 0, &width[i]); _get_column_int(stmt, 1, &height[i]); } if (_convert_to_support_size(width, height, count)) { _E("failed to convert size"); free(width); free(height); sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; } *w = width; *h = height; *cnt = count; sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_NONE; } static int _get_widget_supported_info(const char *widget_id, uid_t uid, int *cnt, int **w, int **h, int **t) { static const char query[] = "SELECT width, height FROM support_size WHERE classid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; int count = 0; int i; int *width; int *height; int *type; db = _open_db(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); while (sqlite3_step(stmt) == SQLITE_ROW) count++; if (count == 0) { sqlite3_finalize(stmt); sqlite3_close_v2(db); *cnt = 0; *w = NULL; *h = NULL; return WIDGET_ERROR_NOT_EXIST; } sqlite3_reset(stmt); width = malloc(sizeof(int) * count); height = malloc(sizeof(int) * count); type = malloc(sizeof(int) * count); for (i = 0; i < count; i++) { sqlite3_step(stmt); _get_column_int(stmt, 0, &width[i]); _get_column_int(stmt, 1, &height[i]); } if (_convert_to_support_info(width, height, type, count)) { _E("failed to convert size"); free(width); free(height); free(type); sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; } *t = type; *w = width; *h = height; *cnt = count; sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_NONE; } static int _instance_cb(const char *widget_id, const char *instance_id, void *data) { int ret; struct widget_instance_info_s *instance_info = (struct widget_instance_info_s *)data; _D("widget_id %s, instance_id %s", widget_id, instance_id); if (strcmp(instance_info->instance_id, instance_id) == 0) { ret = widget_instance_change_period(widget_id, instance_id, instance_info->period); _D("ret %d ", ret); if (ret > 0) instance_info->exists = true; } return WIDGET_ERROR_NONE; } EAPI int widget_service_change_period(const char *pkgname, const char *id, double period) { widget_instance_h instance; struct widget_instance_info_s instance_info; int ret; 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; } instance = widget_instance_get_instance(pkgname, id); if (!instance) { instance_info.instance_id = id; instance_info.exists = false; instance_info.period = period; ret = widget_service_get_widget_instance_list(pkgname, _instance_cb, &instance_info); _D("get list ret %d, %d", ret, instance_info.exists); if (ret == 0 || !instance_info.exists) { _E("instance not exists or out of bound(package)"); return WIDGET_ERROR_PERMISSION_DENIED; } ret = WIDGET_ERROR_NONE; } else { ret = widget_instance_change_period(pkgname, id, period); widget_instance_unref(instance); if (ret > 0) ret = WIDGET_ERROR_NONE; } return ret; } EAPI int widget_service_trigger_update(const char *widget_id, const char *id, bundle *b, int force) { int ret; bundle_raw *raw = NULL; int len; if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (!widget_id) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } if (b) bundle_encode(b, &raw, &len); ret = widget_instance_trigger_update_v2(widget_id, id, (const char *)raw, force); if (raw) free(raw); return ret; } 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, prime 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; struct widget_list_item *item; 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(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; ret = sqlite3_prepare_v2(db, query_buf, strlen(query_buf), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); return WIDGET_ERROR_FAULT; /* LCOV_EXCL_STOP */ } if (pkgid != NULL) sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC); while (sqlite3_step(stmt) == SQLITE_ROW) { item = calloc(1, sizeof(struct widget_list_item)); if (item == NULL) { /* LCOV_EXCL_START */ _E("out of memory"); sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_STOP */ } _get_column_str(stmt, 0, &item->classid); _get_column_str(stmt, 1, &item->pkgid); _get_column_int(stmt, 2, &item->is_prime); *list = g_list_append(*list, item); } sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_NONE; } EAPI int widget_service_get_widget_list(widget_list_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 (cb == NULL) { _E("invalid parameter"); 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 && !_is_global(getuid())) ret = _get_widget_list(NULL, GLOBALAPP_USER, &list); 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; } ret = g_list_length(list); g_list_free_full(list, __free_widget_list); if (ret == 0) return WIDGET_ERROR_NOT_EXIST; 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; } 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 && !_is_global(getuid())) 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' */ if (cb(item->classid, item->is_prime, data) != WIDGET_ERROR_NONE) break; } ret = g_list_length(list); g_list_free_full(list, __free_widget_list); return ret; } static char *_get_main_app_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; pkgmgrinfo_pkginfo_h pkginfo; char *mainappid; char *appid; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &pkgid); sqlite3_finalize(stmt); sqlite3_close_v2(db); ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, getuid(), &pkginfo); free(pkgid); if (ret != PMINFO_R_OK) { set_last_result(WIDGET_ERROR_FAULT); return NULL; } ret = pkgmgrinfo_pkginfo_get_mainappid(pkginfo, &mainappid); if (ret != PMINFO_R_OK) { _E("failed to get mainappid of widget %s", widget_id); set_last_result(WIDGET_ERROR_FAULT); pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo); return NULL; } appid = strdup(mainappid); pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo); set_last_result(WIDGET_ERROR_NONE); 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; } 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 && !_is_global(getuid())) 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) { int ret; int *width = NULL; int *height = NULL; if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (widget_id == NULL || cnt == NULL || types == NULL) { _E("invalid parameter"); 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_info(widget_id, getuid(), cnt, &width, &height, types); if (ret == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) ret = _get_widget_supported_info(widget_id, GLOBALAPP_USER, cnt, &width, &height, types); 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) { return ret; } free(width); free(height); return WIDGET_ERROR_NONE; } 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=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; char *appid; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &appid); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return appid; } EAPI char *widget_service_get_app_id_of_setup_app(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; } 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 && !_is_global(getuid())) appid = _get_app_id_of_setup_app(widget_id, GLOBALAPP_USER); return appid; } static int _get_nodisplay(const char *widget_id, uid_t uid) { static const char query[] = "SELECT nodisplay FROM widget_class WHERE classid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; int nodisplay = 0; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return 0; } 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); set_last_result(WIDGET_ERROR_FAULT); return 0; } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return 0; } _get_column_int(stmt, 0, &nodisplay); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return nodisplay; } static int _get_update_period(const char *widget_id, uid_t uid, double *period) { static const char query[] = "SELECT update_period FROM widget_class WHERE classid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; db = _open_db(uid); if (db == NULL) { return WIDGET_ERROR_IO_ERROR; } 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; } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); if (ret == SQLITE_DONE) return WIDGET_ERROR_NOT_EXIST; return WIDGET_ERROR_FAULT; } _get_column_double(stmt, 0, period); sqlite3_finalize(stmt); sqlite3_close_v2(db); return WIDGET_ERROR_NONE; } int widget_service_get_update_period(const char *widget_id, double *period) { int ret = _get_update_period(widget_id, getuid(), period); if (ret == WIDGET_ERROR_NOT_EXIST) ret = _get_update_period(widget_id, GLOBALAPP_USER, period); return ret; } EAPI int widget_service_get_nodisplay(const char *widget_id) { int 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; } 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 && !_is_global(getuid())) nodisplay = _get_nodisplay(widget_id, GLOBALAPP_USER); return 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) { if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (!pkgid) { _E("invalid parameter"); 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; } /* 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) { if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (!pkgid) { _E("invalid parameter"); 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; } /* 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) { if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (!pkgid) { _E("invalid parameter"); 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; } 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 " "classid=? AND width=? AND height=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; char *path; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 2, width); sqlite3_bind_int(stmt, 3, height); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &path); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return path; } static int update_lang_info(void) { char *syslang; UErrorCode err; int country_len; syslang = vconf_get_str(VCONFKEY_LANGSET); if (!syslang) { ErrPrint("Failed to get vconf-lang"); return -EFAULT; } if (_syslang && !strcmp(_syslang, syslang)) { _D("Syslang is not changed: %s", syslang); free(syslang); return 0; } free(_syslang); _syslang = syslang; err = U_ZERO_ERROR; uloc_setDefault((const char *)_syslang, &err); if (!U_SUCCESS(err)) { _E("Failed to set default lang: %s", u_errorName(err)); free(_syslang); _syslang = NULL; return -EFAULT; } _iso3lang = uloc_getISO3Language(uloc_getDefault()); if (!_iso3lang || !strlen(_iso3lang)) { _E("Failed to get iso3lang"); free(_syslang); _syslang = NULL; return -EFAULT; } err = U_ZERO_ERROR; country_len = uloc_getCountry(uloc_getDefault(), _country, ULOC_COUNTRY_CAPACITY, &err); if (!U_SUCCESS(err) || country_len <= 0) { _E("Failed to get locale: %s, %s, %d (%s)", u_errorName(err), _iso3lang, country_len, _country); free(_syslang); _syslang = NULL; return -EFAULT; } return 0; } EAPI char *widget_service_get_preview_image_path(const char *widget_id, widget_size_type_e size_type) { char *path; int w = -1; int h = -1; char *lang_path; int buf_len; int i; int printed; 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 (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { set_last_result(WIDGET_ERROR_PERMISSION_DENIED); return NULL; } _convert_type_to_support_size_ratio(size_type, &w, &h); path = _get_preview_image_path(widget_id, w, h, getuid()); if (path == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) path = _get_preview_image_path(widget_id, w, h, GLOBALAPP_USER); if (path == NULL) { _E("Can not find preview path"); set_last_result(WIDGET_ERROR_INVALID_PARAMETER); return NULL; } if (update_lang_info() != 0) return path; buf_len = strlen(path) + strlen(_iso3lang) + strlen(_country) + 3; /* '/' '-' '/' */ lang_path = malloc(buf_len + 1); if (!lang_path) { set_last_result(WIDGET_ERROR_OUT_OF_MEMORY); _E("Heap: %d", errno); free(path); return NULL; } for (i = strlen(path); i >= 0 && path[i] != '/'; i--); i++; /* Skip '/' */ strncpy(lang_path, path, i); printed = snprintf(lang_path + i, buf_len - i, "%s-%s/%s", _iso3lang, _country, path + i); if (lang_path[i + printed] != '\0') { _E("Path is truncated"); lang_path[i + printed] = '\0'; } if (access(lang_path, R_OK) != 0) { _D("Access failed: %s, %d", lang_path, errno); free(lang_path); } else { free(path); path = lang_path; } return path; } static char *_get_main_widget_id(const char *pkg_id, uid_t uid) { static const char query[] = "SELECT classid FROM widget_class " "WHERE pkgid=? and prime=1 "; int ret; sqlite3 *db; sqlite3_stmt *stmt; char *widget_id; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, pkg_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { if (ret == SQLITE_DONE) _E("cannot find widget_id for pkg_id %s", pkg_id); else _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &widget_id); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return widget_id; } 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; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); if (lang) sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_STATIC); else sqlite3_bind_null(stmt, 2); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { if (ret == SQLITE_DONE) _E("cannot find icon for widget %s", widget_id); else _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &icon); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return icon; } EAPI char *widget_service_get_icon(const char *pkgid, const char *lang) { char *icon; char *widget_id; if (!_is_widget_feature_enabled()) { _E("not supported"); set_last_result(WIDGET_ERROR_NOT_SUPPORTED); return NULL; } if (pkgid == NULL) { _E("invalid parameter"); 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; } widget_id = _get_main_widget_id(pkgid, getuid()); if (widget_id == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) widget_id = _get_main_widget_id(pkgid, GLOBALAPP_USER); icon = _get_icon(widget_id, lang, getuid()); if (icon == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) 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 (LOWER(locale)=LOWER(?) 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; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("step error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); if (lang) sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_STATIC); else sqlite3_bind_null(stmt, 2); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { if (ret == SQLITE_DONE) _E("cannot find label for widget %s", widget_id); else _E("step error: %s", sqlite3_errmsg(db)); _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &label); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return label; } static char *__get_cur_locale(void) { char *language; char *ptr; language = vconf_get_str(VCONFKEY_LANGSET); if (language) { ptr = language; while (*ptr) { if (*ptr == '.') { *ptr = '\0'; break; } if (*ptr == '_') { *ptr = '-'; } ptr++; } } else { language = strdup("en-us"); } return language; } EAPI char *widget_service_get_name(const char *widget_id, const char *lang) { char *name; char *language; 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; } if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { set_last_result(WIDGET_ERROR_PERMISSION_DENIED); return NULL; } if (!lang) language = __get_cur_locale(); else language = strdup(lang); if (!language) { _E("Out-of-memory"); set_last_result(WIDGET_ERROR_OUT_OF_MEMORY); return NULL; } name = _get_name(widget_id, language, getuid()); if (name == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) name = _get_name(widget_id, language, GLOBALAPP_USER); free(language); 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; } if (widget_id == NULL || cnt == NULL || w == NULL || h == NULL) { _E("invalid parameter"); 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 && !_is_global(getuid())) 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; } static char *_get_widget_id(const char *appid, uid_t uid) { static const char query[] = "SELECT classid FROM widget_class WHERE appid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; char *classid; db = _open_db(uid); if (db == NULL) { set_last_result(WIDGET_ERROR_IO_ERROR); return NULL; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &classid); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); return classid; } static char *__get_widget_main_appid_from_pkgid_or_appid(const char *id) { pkgmgrinfo_appinfo_h appinfo = NULL; pkgmgrinfo_pkginfo_h pkginfo = NULL; char *new_pkgid = NULL; char *pkgid = NULL; GList *widget_list = NULL; GList *iter; char *widget_id = NULL; int ret; struct widget_list_item *item; ret = pkgmgrinfo_pkginfo_get_pkginfo(id, &pkginfo); if (ret != PMINFO_R_OK) { ret = pkgmgrinfo_appinfo_get_appinfo(id, &appinfo); if (ret != PMINFO_R_OK) { _E("Failed to get app/pkg info - %s", id); return NULL; } ret = pkgmgrinfo_appinfo_get_pkgid(appinfo, &pkgid); if (ret != PMINFO_R_OK) { _E("Failed to get pkgid - %s", id); pkgmgrinfo_appinfo_destroy_appinfo(appinfo); return NULL; } ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &pkginfo); if (ret != PMINFO_R_OK) { _E("Failed to get pkginfo - %s", id); pkgmgrinfo_appinfo_destroy_appinfo(appinfo); return NULL; } new_pkgid = strdup(pkgid); pkgmgrinfo_appinfo_destroy_appinfo(appinfo); if (new_pkgid == NULL) { _E("out of memory"); return NULL; } id = new_pkgid; } ret = _get_widget_list(id, getuid(), &widget_list); if ((ret != WIDGET_ERROR_NONE || widget_list == NULL) && !_is_global(getuid())) ret = _get_widget_list(id, GLOBALAPP_USER, &widget_list); if (widget_list == NULL) goto end; iter = g_list_first(widget_list); while (iter) { item = (struct widget_list_item *)iter->data; iter = g_list_next(iter); if (item) { widget_list = g_list_remove(widget_list, item); if (item->is_prime) { if (widget_id) free(widget_id); widget_id = strdup(item->classid); } if (widget_id == NULL) widget_id = strdup(item->classid); free(item->classid); free(item->pkgid); free(item); } } end: pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo); if (new_pkgid) free(new_pkgid); return widget_id; } EAPI char *widget_service_get_widget_id(const char *appid) { char *classid; char *widget_id; 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; } if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { set_last_result(WIDGET_ERROR_PERMISSION_DENIED); return NULL; } classid = _get_widget_id(appid, getuid()); if (classid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) classid = _get_widget_id(appid, GLOBALAPP_USER); if (classid) return classid; else if (get_last_result() != WIDGET_ERROR_NOT_EXIST) return NULL; widget_id = __get_widget_main_appid_from_pkgid_or_appid(appid); if (widget_id == NULL) { _E("Failed to get widget id"); return NULL; } classid = _get_widget_id(widget_id, getuid()); if (classid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) classid = _get_widget_id(widget_id, GLOBALAPP_USER); free(widget_id); 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; } ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { /* LCOV_EXCL_START */ _E("prepare error: %s", sqlite3_errmsg(db)); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_FAULT); return NULL; /* LCOV_EXCL_STOP */ } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); /* TODO: which error should be set? */ set_last_result(ret == SQLITE_DONE ? WIDGET_ERROR_NOT_EXIST : WIDGET_ERROR_FAULT); return NULL; } _get_column_str(stmt, 0, &pkgid); sqlite3_finalize(stmt); sqlite3_close_v2(db); set_last_result(WIDGET_ERROR_NONE); 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; } if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) { set_last_result(WIDGET_ERROR_PERMISSION_DENIED); return NULL; } pkgid = _get_package_id(widget_id, getuid()); if (pkgid == NULL && get_last_result() == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) 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) { if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (width == NULL || height == NULL) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } if (_get_supported_size(type, width, height)) return WIDGET_ERROR_INVALID_PARAMETER; return WIDGET_ERROR_NONE; } EAPI int widget_service_get_size_type(int width, int height, widget_size_type_e *size_type) { if (!_is_widget_feature_enabled()) { _E("not supported"); return WIDGET_ERROR_NOT_SUPPORTED; } if (width <= 0 || height <= 0 || size_type == NULL) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } if (_get_supported_size_type(width, height, (int *)size_type)) return WIDGET_ERROR_INVALID_PARAMETER; return WIDGET_ERROR_NONE; } EAPI int widget_service_get_content_of_widget_instance(const char *widget_id, const char *widget_instance_id, bundle **b) { char *raw = NULL; int ret; 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; } ret = aul_widget_instance_get_content(widget_id, widget_instance_id, &raw); if (raw) { *b = bundle_decode((const bundle_raw *)raw, strlen(raw)); free(raw); return WIDGET_ERROR_NONE; } switch (ret) { case AUL_R_EINVAL: ret = WIDGET_ERROR_INVALID_PARAMETER; break; case AUL_R_ECOMM: ret = WIDGET_ERROR_IO_ERROR; break; case AUL_R_ENOAPP: ret = WIDGET_ERROR_NOT_EXIST; break; case AUL_R_EILLACC: ret = WIDGET_ERROR_PERMISSION_DENIED; break; default: ret = WIDGET_ERROR_FAULT; } return ret; } struct instance_cb { const char *widget_id; widget_instance_list_cb cb; void *data; int cnt; }; static void __instance_list_cb(const char *instance_id, void *user_data) { struct instance_cb *cb_data = (struct instance_cb *)user_data; cb_data->cnt++; _D("instance list: %s %s", cb_data->widget_id, instance_id); if (cb_data && cb_data->cb) cb_data->cb(cb_data->widget_id, instance_id, cb_data->data); } EAPI int widget_service_get_widget_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data) { struct instance_cb cb_data; int ret = WIDGET_ERROR_NONE; cb_data.widget_id = widget_id; cb_data.cb = cb; cb_data.data = data; cb_data.cnt = 0; 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 = aul_widget_instance_foreach(widget_id, __instance_list_cb, &cb_data); if (ret == AUL_R_EILLACC) return WIDGET_ERROR_PERMISSION_DENIED; if (ret == AUL_R_ENOAPP || cb_data.cnt == 0) return WIDGET_ERROR_NOT_EXIST; return cb_data.cnt; } 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, cb_info->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"); return WIDGET_ERROR_NOT_SUPPORTED; } if (cb == NULL) { _E("invalid parameter"); return WIDGET_ERROR_INVALID_PARAMETER; } 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) { 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; } 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; } static int __get_max_instance(const char *widget_id, uid_t uid) { static const char query[] = "SELECT max_instance FROM widget_class WHERE classid=?"; int ret; sqlite3 *db; sqlite3_stmt *stmt; int max_instance = 0; db = _open_db(uid); if (db == NULL) return WIDGET_ERROR_IO_ERROR; 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; } sqlite3_bind_text(stmt, 1, widget_id, -1, SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret != SQLITE_ROW) { _E("step error: %s", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close_v2(db); if (ret == SQLITE_DONE) return WIDGET_ERROR_NOT_EXIST; return WIDGET_ERROR_FAULT; } _get_column_int(stmt, 0, &max_instance); _D("widget_id: %s, max-instance: %d", widget_id, max_instance); sqlite3_finalize(stmt); sqlite3_close_v2(db); return max_instance; } EAPI int widget_service_get_widget_max_count(const char *widget_id) { int ret; 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; } if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) return WIDGET_ERROR_PERMISSION_DENIED; ret = __get_max_instance(widget_id, getuid()); if (ret == WIDGET_ERROR_NOT_EXIST && !_is_global(getuid())) ret = __get_max_instance(widget_id, GLOBALAPP_USER); return ret; } EAPI int widget_service_get_instance_count(const char *widget_id, const char *cluster, const char *category) { int ret; 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; } if (check_privilege("http://tizen.org/privilege/widget.viewer") < 0) return WIDGET_ERROR_PERMISSION_DENIED; ret = aul_widget_instance_count(widget_id); if (ret == AUL_R_EILLACC) return WIDGET_ERROR_PERMISSION_DENIED; return ret; }