2 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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>
36 #include "shortcut_internal.h"
42 #define CREATED 0x00BEEF00
43 #define DESTROYED 0x00DEAD00
48 int (*init_cb)(int status, void *data);
52 const char *utility_socket;
54 struct dlist *pending_list;
61 .utility_socket = "/tmp/.utility.service",
68 struct shortcut_icon *handle;
69 icon_request_cb_t result_cb;
76 struct request_item *item;
77 struct packet *packet;
95 struct shortcut_icon {
97 struct shortcut_desc *desc;
104 struct shortcut_desc {
107 unsigned int last_idx;
109 struct dlist *block_list;
114 static inline void delete_block(struct block *block)
116 DbgPrint("Release block: %p\n", block);
122 free(block->target_id);
128 static inline int shortcut_icon_desc_close(struct shortcut_desc *handle)
134 dlist_foreach_safe(handle->block_list, l, n, block) {
135 handle->block_list = dlist_remove(handle->block_list, l);
145 static inline struct shortcut_icon *shortcut_icon_request_unref(struct shortcut_icon *handle)
148 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
150 if (handle->refcnt == 0) {
151 handle->state = DESTROYED;
152 shortcut_icon_desc_close(handle->desc);
162 static inline struct shortcut_icon *shortcut_icon_request_ref(struct shortcut_icon *handle)
165 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
171 static int disconnected_cb(int handle, void *data)
173 if (s_info.fd != handle)
176 ErrPrint("Disconnected\n");
178 s_info.init_cb = NULL;
179 s_info.cbdata = NULL;
180 s_info.initialized = 0;
186 static inline struct shortcut_desc *shortcut_icon_desc_open(void)
188 struct shortcut_desc *handle;
190 handle = calloc(1, sizeof(*handle));
192 ErrPrint("Error: %s\n", strerror(errno));
201 static inline int shortcut_icon_desc_save(struct shortcut_desc *handle, const char *filename)
211 fp = fopen(filename, "w+t");
213 ErrPrint("Error: %s\n", strerror(errno));
217 DbgPrint("Close and flush\n");
218 dlist_foreach_safe(handle->block_list, l, n, block) {
222 fprintf(fp, "type=%s\n", block->type);
223 DbgPrint("type=%s\n", block->type);
227 fprintf(fp, "part=%s\n", block->part);
228 DbgPrint("part=%s\n", block->part);
232 fprintf(fp, "data=%s\n", block->data);
233 DbgPrint("data=%s\n", block->data);
237 fprintf(fp, "option=%s\n", block->option);
238 DbgPrint("option=%s\n", block->option);
242 fprintf(fp, "id=%s\n", block->id);
243 DbgPrint("id=%s\n", block->id);
246 if (block->target_id) {
247 fprintf(fp, "target=%s\n", block->target_id);
248 DbgPrint("target=%s\n", block->target_id);
261 static inline struct block *find_block(struct shortcut_desc *handle, const char *id, const char *part)
266 dlist_foreach(handle->block_list, l, block) {
267 if (!strcmp(block->part, part) && (!id || !strcmp(block->id, id)))
276 static inline int update_block(struct block *block, const char *data, const char *option)
279 char *_option = NULL;
282 _data = strdup(data);
284 ErrPrint("Heap: %s\n", strerror(errno));
290 _option = strdup(option);
292 ErrPrint("Heap: %s\n", strerror(errno));
301 block->option = _option;
313 static inline int shortcut_icon_desc_add_block(struct shortcut_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option, const char *target_id)
317 if (!handle || !type)
318 return SHORTCUT_ERROR_INVALID;
327 if (strcmp(type, SHORTCUT_ICON_TYPE_SCRIPT)) {
328 ErrPrint("target id only can be used for script type\n");
333 block = find_block(handle, id, part);
335 block = calloc(1, sizeof(*block));
337 ErrPrint("Heap: %s\n", strerror(errno));
338 return SHORTCUT_ERROR_MEMORY;
341 block->type = strdup(type);
343 ErrPrint("Heap: %s\n", strerror(errno));
345 return SHORTCUT_ERROR_MEMORY;
348 block->part = strdup(part);
350 ErrPrint("Heap: %s\n", strerror(errno));
353 return SHORTCUT_ERROR_MEMORY;
356 block->data = strdup(data);
358 ErrPrint("Heap: %s\n", strerror(errno));
362 return SHORTCUT_ERROR_MEMORY;
366 block->option = strdup(option);
367 if (!block->option) {
368 ErrPrint("Heap: %s\n", strerror(errno));
373 return SHORTCUT_ERROR_MEMORY;
378 block->id = strdup(id);
380 ErrPrint("Heap: %s\n", strerror(errno));
386 return SHORTCUT_ERROR_MEMORY;
391 block->target_id = strdup(target_id);
392 if (!block->target_id) {
393 ErrPrint("Heap: %s\n", strerror(errno));
400 return SHORTCUT_ERROR_MEMORY;
404 block->idx = handle->last_idx++;
405 handle->block_list = dlist_append(handle->block_list, block);
407 if (strcmp(block->type, type) || strcmp(block->target_id, target_id)) {
408 ErrPrint("type or target id is not valid (%s, %s) or (%s, %s)\n",
409 block->type, type, block->target_id, target_id);
413 update_block(block, data, option);
421 static int icon_request_cb(pid_t pid, int handle, const struct packet *packet, void *data)
423 struct request_item *item = data;
428 DbgPrint("Disconnected?\n");
430 if (packet_get(packet, "i", &ret) != 1) {
431 DbgPrint("Invalid packet\n");
437 item->result_cb(item->handle, ret, item->data);
439 (void)shortcut_icon_request_unref(item->handle);
446 static inline int make_connection(void)
449 static struct method service_table[] = {
456 s_info.fd = com_core_packet_client_init(s_info.utility_socket, 0, service_table);
458 ret = SHORTCUT_ERROR_COMM;
461 s_info.init_cb(ret, s_info.cbdata);
465 struct pending_item *pend;
468 s_info.init_cb(SHORTCUT_SUCCESS, s_info.cbdata);
470 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
471 s_info.pending_list = dlist_remove(s_info.pending_list, l);
473 ret = com_core_packet_async_send(s_info.fd, pend->packet, 0.0f, icon_request_cb, pend->item);
474 packet_destroy(pend->packet);
476 ErrPrint("ret: %d\n", ret);
477 if (pend->item->result_cb)
478 pend->item->result_cb(pend->item->handle, ret, pend->item->data);
485 ret = SHORTCUT_SUCCESS;
493 static void master_started_cb(keynode_t *node, void *user_data)
497 if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0)
498 ErrPrint("Unable to get \"%s\"\n", VCONFKEY_MASTER_STARTED);
500 if (state == 1 && make_connection() == SHORTCUT_SUCCESS) {
502 ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
503 DbgPrint("Ignore VCONF [%d]\n", ret);
509 EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
516 if (s_info.initialized) {
517 s_info.initialized = 1;
518 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
521 s_info.init_cb = init_cb;
522 s_info.cbdata = data;
524 ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
526 ErrPrint("Failed to add vconf for service state [%d]\n", ret);
528 DbgPrint("vconf is registered\n");
530 master_started_cb(NULL, NULL);
536 EAPI int shortcut_icon_service_fini(void)
540 struct pending_item *pend;
542 if (s_info.initialized) {
543 com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
544 s_info.initialized = 0;
550 com_core_packet_client_fini(s_info.fd);
551 s_info.init_cb = NULL;
552 s_info.cbdata = NULL;
555 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
556 s_info.pending_list = dlist_remove(s_info.pending_list, l);
557 packet_unref(pend->packet);
558 if (pend->item->result_cb)
559 pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
568 EAPI struct shortcut_icon *shortcut_icon_request_create(void)
570 struct shortcut_icon *handle;
572 handle = malloc(sizeof(*handle));
574 ErrPrint("Heap: %s\n", strerror(errno));
578 handle->desc = shortcut_icon_desc_open();
580 ErrPrint("Uanble to open desc\n");
585 handle->state = CREATED;
591 EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
593 if (!handle || handle->state != CREATED) {
594 ErrPrint("Handle is not valid\n");
604 EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
606 if (!handle || handle->state != CREATED) {
607 ErrPrint("Handle is not valid\n");
616 EAPI int shortcut_icon_request_set_info(struct shortcut_icon *handle, const char *id, const char *type, const char *part, const char *data, const char *option, const char *subid)
618 if (!handle || handle->state != CREATED) {
619 ErrPrint("Handle is not valid\n");
623 return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
628 EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
630 if (!handle || handle->state != CREATED) {
631 ErrPrint("Handle is not valid\n");
635 (void)shortcut_icon_request_unref(handle);
641 EAPI int shortcut_icon_request_send(struct shortcut_icon *handle, int size_type, const char *layout, const char *group, const char *outfile, icon_request_cb_t result_cb, void *data)
644 struct packet *packet;
645 struct request_item *item;
649 if (!handle || handle->state != CREATED) {
650 ErrPrint("Handle is not valid\n");
655 layout = DEFAULT_ICON_LAYOUT;
658 group = DEFAULT_ICON_GROUP;
660 len = strlen(outfile) + strlen(".desc") + 1;
661 filename = malloc(len);
663 ErrPrint("Heap: %s\n", strerror(errno));
667 snprintf(filename, len, "%s.desc", outfile);
669 ret = shortcut_icon_desc_save(handle->desc, filename);
673 item = malloc(sizeof(*item));
675 ErrPrint("Heap: %s\n", strerror(errno));
676 if (unlink(filename) < 0)
677 ErrPrint("Unlink: %s\n", strerror(errno));
682 item->result_cb = result_cb;
684 item->handle = shortcut_icon_request_ref(handle);
686 packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
688 ErrPrint("Failed to create a packet\n");
689 if (unlink(filename) < 0)
690 ErrPrint("Unlink: %s\n", strerror(errno));
692 (void)shortcut_icon_request_unref(handle);
697 if (s_info.fd >= 0 && !s_info.pending_list) {
698 ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
699 packet_destroy(packet);
701 ErrPrint("ret: %d\n", ret);
702 if (unlink(filename) < 0)
703 ErrPrint("Unlink: %s\n", strerror(errno));
705 (void)shortcut_icon_request_unref(handle);
707 DbgPrint("Request is sent\n");
709 struct pending_item *pend;
711 pend = malloc(sizeof(*pend));
713 ErrPrint("Heap: %s\n", strerror(errno));
714 packet_destroy(packet);
716 if (unlink(filename) < 0)
717 ErrPrint("Unlink: %s\n", strerror(errno));
718 (void)shortcut_icon_request_unref(handle);
723 pend->packet = packet;
726 s_info.pending_list = dlist_append(s_info.pending_list, pend);
727 DbgPrint("Request is pended\n");