2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <sys/socket.h>
23 #include <sys/ioctl.h>
30 #include <vconf-keys.h>
34 #include <com-core_packet.h>
39 #define DbgPrint(format, arg...) LOGD("[
\e[32m%s/%s
\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
40 #define ErrPrint(format, arg...) LOGE("[
\e[32m%s/%s
\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
42 extern FILE *__file_log_fp;
43 #define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [
\e[32m%s/%s
\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
45 #define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [
\e[32m%s/%s
\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
48 #define EAPI __attribute__((visibility("default")))
59 const char *socket_file;
61 int (*request_cb)(const char *appid, const char *name, int type, const char *content, const char *icon, pid_t pid, double period, void *data);
69 .socket_file = "/tmp/.shortcut",
70 .dbfile = "/opt/dbspace/.shortcut_service.db",
78 static struct packet *add_shortcut_handler(pid_t pid, int handle, const struct packet *packet)
90 if (packet_get(packet, "ssiss", &appid, &name, &type, &content, &icon) != 5) {
91 ErrPrint("Invalid packet\n");
95 DbgPrint("appid[%s], name[%s], type[0x%x], content[%s], icon[%s]\n", appid, name, type, content, icon);
97 if (s_info.server_cb.request_cb)
98 ret = s_info.server_cb.request_cb(appid, name, type, content, icon, pid, -1.0f, s_info.server_cb.data);
102 return packet_create_reply(packet, "i", ret);
107 static struct packet *add_livebox_handler(pid_t pid, int handle, const struct packet *packet)
120 if (packet_get(packet, "ssissd", &appid, &name, &type, &content, &icon, &period) != 6) {
121 ErrPrint("Invalid packet\n");
125 DbgPrint("appid[%s], name[%s], type[0x%x], content[%s], icon[%s], period[%lf]\n", appid, name, type, content, icon, period);
127 if (s_info.server_cb.request_cb)
128 ret = s_info.server_cb.request_cb(appid, name, type, content, icon, pid, period, s_info.server_cb.data);
132 return packet_create_reply(packet, "i", ret);
137 EAPI int shortcut_set_request_cb(request_cb_t request_cb, void *data)
139 s_info.server_cb.request_cb = request_cb;
140 s_info.server_cb.data = data;
142 if (s_info.server_fd < 0) {
143 static struct method service_table[] = {
145 .cmd = "add_shortcut",
146 .handler = add_shortcut_handler,
149 .cmd = "add_livebox",
150 .handler = add_livebox_handler,
158 unlink(s_info.socket_file); /* Delete previous socket file for creating a new server socket */
159 s_info.server_fd = com_core_packet_server_init(s_info.socket_file, service_table);
162 DbgPrint("Server FD: %d\n", s_info.server_fd);
164 return s_info.server_fd > 0 ? 0 : s_info.server_fd;
169 struct result_cb_item {
170 result_cb_t result_cb;
176 static int shortcut_send_cb(pid_t pid, int handle, const struct packet *packet, void *data)
178 struct result_cb_item *item = data;
182 ErrPrint("Packet is not valid\n");
184 } else if (packet_get(packet, "i", &ret) != 1) {
185 ErrPrint("Packet is not valid\n");
190 ret = item->result_cb(ret, pid, item->data);
199 static int livebox_send_cb(pid_t pid, int handle, const struct packet *packet, void *data)
201 struct result_cb_item *item = data;
205 ErrPrint("Packet is not valid\n");
207 } else if (packet_get(packet, "i", &ret) != 1) {
208 ErrPrint("Packet is not valid\n");
213 ret = item->result_cb(ret, pid, item->data);
222 static int disconnected_cb(int handle, void *data)
224 if (s_info.client_fd != handle) {
225 /*!< This is not my favor */
229 s_info.client_fd = -EINVAL;
235 EAPI int add_to_home_shortcut(const char *appid, const char *name, int type, const char *content, const char *icon, result_cb_t result_cb, void *data)
237 struct packet *packet;
238 struct result_cb_item *item;
241 if (!s_info.initialized) {
242 s_info.initialized = 1;
243 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
246 if (s_info.client_fd < 0) {
247 static struct method service_table[] = {
254 s_info.client_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
255 if (s_info.client_fd < 0) {
256 ErrPrint("Failed to make connection\n");
257 return s_info.client_fd;
261 item = malloc(sizeof(*item));
263 ErrPrint("Heap: %s\n", strerror(errno));
267 item->result_cb = result_cb;
282 packet = packet_create("add_shortcut", "ssiss", appid, name, type, content, icon);
284 ErrPrint("Failed to build a packet\n");
289 ret = com_core_packet_async_send(s_info.client_fd, packet, 0.0f, shortcut_send_cb, item);
291 packet_destroy(packet);
293 com_core_packet_client_fini(s_info.client_fd);
294 s_info.client_fd = -1;
302 EAPI int add_to_home_livebox(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data)
304 struct packet *packet;
305 struct result_cb_item *item;
308 if (!s_info.initialized) {
309 s_info.initialized = 1;
310 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
313 if (s_info.client_fd < 0) {
314 static struct method service_table[] = {
321 s_info.client_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
322 if (s_info.client_fd < 0)
323 return s_info.client_fd;
326 item = malloc(sizeof(*item));
328 ErrPrint("Heap: %s\n", strerror(errno));
332 item->result_cb = result_cb;
335 packet = packet_create("add_livebox", "ssissd", appid, name, type, content, icon, period);
337 ErrPrint("Failed to build a packet\n");
342 ret = com_core_packet_async_send(s_info.client_fd, packet, 0.0f, livebox_send_cb, item);
344 packet_destroy(packet);
346 com_core_packet_client_fini(s_info.client_fd);
347 s_info.client_fd = -1;
354 EAPI int shortcut_add_to_home_with_period(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data)
356 return add_to_home_livebox(appid, name, type, content, icon, period, result_cb, data);
359 EAPI int shortcut_add_to_home(const char *appid, const char *name, int type, const char *content, const char *icon, result_cb_t result_cb, void *data)
361 return add_to_home_shortcut(appid, name, type, content, icon, result_cb, data);
364 static inline int open_db(void)
368 ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
369 if (ret != SQLITE_OK) {
370 DbgPrint("Failed to open a %s\n", s_info.dbfile);
380 * \note this function will returns allocated(heap) string
382 static inline char *get_i18n_name(const char *lang, int id)
385 static const char *query = "SELECT name FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE";
386 const unsigned char *name;
390 status = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
391 if (status != SQLITE_OK) {
392 ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(s_info.handle));
396 status = sqlite3_bind_int(stmt, 1, id);
397 if (status != SQLITE_OK) {
398 ErrPrint("Failed to bind id: %s\n", sqlite3_errmsg(s_info.handle));
403 status = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
404 if (status != SQLITE_OK) {
405 ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(s_info.handle));
410 DbgPrint("id: %d, lang: %s\n", id, lang);
411 if (SQLITE_ROW != sqlite3_step(stmt)) {
412 ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(s_info.handle));
417 name = sqlite3_column_text(stmt, 0);
418 ret = name ? strdup((const char *)name) : NULL;
422 sqlite3_clear_bindings(stmt);
423 sqlite3_finalize(stmt);
429 static inline int homescreen_get_i18n(const char *appid, const char *lang, char **name, char **desc)
432 static const char *query = "SELECT name, desc FROM desc WHERE appid = ? AND lang = ?";
433 const unsigned char *_name;
434 const unsigned char *_desc;
437 status = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
438 if (status != SQLITE_OK) {
439 ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(s_info.handle));
443 status = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
444 if (status != SQLITE_OK) {
445 ErrPrint("Failed to bind appid: %s\n", sqlite3_errmsg(s_info.handle));
450 status = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
451 if (status != SQLITE_OK) {
452 ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(s_info.handle));
457 if (SQLITE_ROW != sqlite3_step(stmt)) {
458 ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(s_info.handle));
464 _name = sqlite3_column_text(stmt, 0);
465 *name = _name ? strdup((const char *)_name) : NULL;
469 _desc = sqlite3_column_text(stmt, 1);
470 *desc = _desc ? strdup((const char *)_desc) : NULL;
475 sqlite3_clear_bindings(stmt);
476 sqlite3_finalize(stmt);
485 EAPI int homescreen_get_description(const char *appid, void (*cb)(const char *appid, const char *icon, const char *name, const char *desc, void *data), void *data)
488 static const char *query = "SELECT icon, name, desc FROM homescreen WHERE appid = ?";
491 const unsigned char *desc;
492 const unsigned char *name;
493 const unsigned char *icon;
496 ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
497 if (ret != SQLITE_OK) {
498 ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
503 ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
504 if (ret != SQLITE_OK) {
505 ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
510 if (SQLITE_ROW != sqlite3_step(stmt)) {
511 ErrPrint("Step failed: %s\n", sqlite3_errmsg(s_info.handle));
516 icon = sqlite3_column_text(stmt, 0);
517 name = sqlite3_column_text(stmt, 1);
518 desc = sqlite3_column_text(stmt, 2);
522 * Get the i18n name and desc
524 if (homescreen_get_i18n(appid, "en-us", &i18n_name, &i18n_desc) < 0) {
529 cb(appid, (const char *)icon, i18n_name ? i18n_name : (const char *)name, i18n_desc ? i18n_desc : (const char *)desc, data);
536 sqlite3_clear_bindings(stmt);
537 sqlite3_finalize(stmt);
543 EAPI char *homescreen_get_image(const char *appid, int idx)
545 static const char *query = "SELECT path FROM image WHERE appid = ? AND id = ?";
548 const unsigned char *path;
549 char *ret_path = NULL;
551 ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
552 if (ret != SQLITE_OK) {
553 ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
557 ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
558 if (ret != SQLITE_OK) {
559 ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
563 ret = sqlite3_bind_int(stmt, 2, idx);
564 if (ret != SQLITE_OK) {
565 ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
569 if (SQLITE_ROW != sqlite3_step(stmt)) {
570 ErrPrint("Step failed: %s\n", sqlite3_errmsg(s_info.handle));
574 path = sqlite3_column_text(stmt, 0);
576 ErrPrint("Get result: %s\n", sqlite3_errmsg(s_info.handle));
580 ret_path = strdup((const char *)path);
582 ErrPrint("Heap: %s\n", strerror(errno));
586 sqlite3_clear_bindings(stmt);
587 sqlite3_finalize(stmt);
593 EAPI int homescreen_get_image_count(const char *appid)
595 static const char *query = "SELECT COUNT(id) FROM image WHERE appid = ?";
599 ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
600 if (ret != SQLITE_OK) {
601 ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
606 ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
607 if (ret != SQLITE_OK) {
608 ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
613 if (SQLITE_ROW != sqlite3_step(stmt)) {
614 ErrPrint("step failed: %s\n", sqlite3_errmsg(s_info.handle));
619 ret = sqlite3_column_int(stmt, 0);
623 sqlite3_clear_bindings(stmt);
624 sqlite3_finalize(stmt);
630 static inline char *cur_locale(void)
633 language = vconf_get_str(VCONFKEY_LANGSET);
650 language = strdup("en-us");
652 ErrPrint("Heap: %s\n", strerror(errno));
663 EAPI int shortcut_get_list(const char *appid, int (*cb)(const char *appid, const char *icon, const char *name, const char *extra_key, const char *extra_data, void *data), void *data)
667 const unsigned char *name;
669 const unsigned char *extra_data;
670 const unsigned char *extra_key;
671 const unsigned char *icon;
677 if (!s_info.db_opened)
678 s_info.db_opened = (open_db() == 0);
680 if (!s_info.db_opened) {
681 ErrPrint("Failed to open a DB\n");
685 language = cur_locale();
687 ErrPrint("Locale is not valid\n");
692 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
693 ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
694 if (ret != SQLITE_OK) {
695 ErrPrint("prepare: %s\n", sqlite3_errmsg(s_info.handle));
700 ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
701 if (ret != SQLITE_OK) {
702 ErrPrint("bind text: %s\n", sqlite3_errmsg(s_info.handle));
703 sqlite3_finalize(stmt);
708 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
709 ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
710 if (ret != SQLITE_OK) {
711 ErrPrint("prepare: %s\n", sqlite3_errmsg(s_info.handle));
718 while (SQLITE_ROW == sqlite3_step(stmt)) {
719 id = sqlite3_column_int(stmt, 0);
721 appid = (const char *)sqlite3_column_text(stmt, 1);
723 LOGE("Failed to get package name\n");
727 name = sqlite3_column_text(stmt, 2);
729 LOGE("Failed to get name\n");
733 extra_key = sqlite3_column_text(stmt, 3);
735 LOGE("Failed to get service\n");
739 extra_data = sqlite3_column_text(stmt, 4);
741 LOGE("Failed to get service\n");
745 icon = sqlite3_column_text(stmt, 5);
747 LOGE("Failed to get icon\n");
753 * Implement the "GET LOCALE" code
755 i18n_name = get_i18n_name(language, id);
758 if (cb(appid, (char *)icon, (i18n_name != NULL ? i18n_name : (char *)name), (char *)extra_key, (char *)extra_data, data) < 0) {
767 sqlite3_clear_bindings(stmt);
768 sqlite3_finalize(stmt);