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) {
177 ErrPrint("Disconnected\n");
179 s_info.init_cb = NULL;
180 s_info.cbdata = NULL;
181 s_info.initialized = 0;
187 static inline struct shortcut_desc *shortcut_icon_desc_open(void)
189 struct shortcut_desc *handle;
191 handle = calloc(1, sizeof(*handle));
193 ErrPrint("Error: %s\n", strerror(errno));
202 static inline int shortcut_icon_desc_save(struct shortcut_desc *handle, const char *filename)
213 fp = fopen(filename, "w+t");
215 ErrPrint("Error: %s\n", strerror(errno));
219 DbgPrint("Close and flush\n");
220 dlist_foreach_safe(handle->block_list, l, n, block) {
224 fprintf(fp, "type=%s\n", block->type);
225 DbgPrint("type=%s\n", block->type);
229 fprintf(fp, "part=%s\n", block->part);
230 DbgPrint("part=%s\n", block->part);
234 fprintf(fp, "data=%s\n", block->data);
235 DbgPrint("data=%s\n", block->data);
239 fprintf(fp, "option=%s\n", block->option);
240 DbgPrint("option=%s\n", block->option);
244 fprintf(fp, "id=%s\n", block->id);
245 DbgPrint("id=%s\n", block->id);
248 if (block->target_id) {
249 fprintf(fp, "target=%s\n", block->target_id);
250 DbgPrint("target=%s\n", block->target_id);
257 if (fclose(fp) != 0) {
258 ErrPrint("fclose: %s\n", strerror(errno));
265 static inline struct block *find_block(struct shortcut_desc *handle, const char *id, const char *part)
270 dlist_foreach(handle->block_list, l, block) {
271 if (!strcmp(block->part, part) && (!id || !strcmp(block->id, id))) {
281 static inline int update_block(struct block *block, const char *data, const char *option)
284 char *_option = NULL;
287 _data = strdup(data);
289 ErrPrint("Heap: %s\n", strerror(errno));
295 _option = strdup(option);
297 ErrPrint("Heap: %s\n", strerror(errno));
306 block->option = _option;
318 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)
322 if (!handle || !type) {
323 return SHORTCUT_ERROR_INVALID;
335 if (strcmp(type, SHORTCUT_ICON_TYPE_SCRIPT)) {
336 ErrPrint("target id only can be used for script type\n");
341 block = find_block(handle, id, part);
343 block = calloc(1, sizeof(*block));
345 ErrPrint("Heap: %s\n", strerror(errno));
346 return SHORTCUT_ERROR_MEMORY;
349 block->type = strdup(type);
351 ErrPrint("Heap: %s\n", strerror(errno));
353 return SHORTCUT_ERROR_MEMORY;
356 block->part = strdup(part);
358 ErrPrint("Heap: %s\n", strerror(errno));
361 return SHORTCUT_ERROR_MEMORY;
364 block->data = strdup(data);
366 ErrPrint("Heap: %s\n", strerror(errno));
370 return SHORTCUT_ERROR_MEMORY;
374 block->option = strdup(option);
375 if (!block->option) {
376 ErrPrint("Heap: %s\n", strerror(errno));
381 return SHORTCUT_ERROR_MEMORY;
386 block->id = strdup(id);
388 ErrPrint("Heap: %s\n", strerror(errno));
394 return SHORTCUT_ERROR_MEMORY;
399 block->target_id = strdup(target_id);
400 if (!block->target_id) {
401 ErrPrint("Heap: %s\n", strerror(errno));
408 return SHORTCUT_ERROR_MEMORY;
412 block->idx = handle->last_idx++;
413 handle->block_list = dlist_append(handle->block_list, block);
415 if (strcmp(block->type, type)) {
416 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
420 if ((block->target_id && !target_id) || (!block->target_id && target_id)) {
421 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
425 if (block->target_id && target_id && strcmp(block->target_id, target_id)) {
426 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
430 update_block(block, data, option);
438 static int icon_request_cb(pid_t pid, int handle, const struct packet *packet, void *data)
440 struct request_item *item = data;
445 DbgPrint("Disconnected?\n");
447 if (packet_get(packet, "i", &ret) != 1) {
448 DbgPrint("Invalid packet\n");
453 if (item->result_cb) {
454 item->result_cb(item->handle, ret, item->data);
457 (void)shortcut_icon_request_unref(item->handle);
464 static inline int make_connection(void)
467 static struct method service_table[] = {
474 s_info.fd = com_core_packet_client_init(s_info.utility_socket, 0, service_table);
476 ret = SHORTCUT_ERROR_COMM;
478 if (s_info.init_cb) {
479 s_info.init_cb(ret, s_info.cbdata);
484 struct pending_item *pend;
486 if (s_info.init_cb) {
487 s_info.init_cb(SHORTCUT_SUCCESS, s_info.cbdata);
490 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
491 s_info.pending_list = dlist_remove(s_info.pending_list, l);
493 ret = com_core_packet_async_send(s_info.fd, pend->packet, 0.0f, icon_request_cb, pend->item);
494 packet_destroy(pend->packet);
496 ErrPrint("ret: %d\n", ret);
497 if (pend->item->result_cb) {
498 pend->item->result_cb(pend->item->handle, ret, pend->item->data);
506 ret = SHORTCUT_SUCCESS;
514 static void master_started_cb(keynode_t *node, void *user_data)
518 if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0) {
519 ErrPrint("Unable to get \"%s\"\n", VCONFKEY_MASTER_STARTED);
522 if (state == 1 && make_connection() == SHORTCUT_SUCCESS) {
524 ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
525 DbgPrint("Ignore VCONF [%d]\n", ret);
531 EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
535 if (s_info.fd >= 0) {
539 if (s_info.initialized) {
540 s_info.initialized = 1;
541 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
544 s_info.init_cb = init_cb;
545 s_info.cbdata = data;
547 ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
549 ErrPrint("Failed to add vconf for service state [%d]\n", ret);
551 DbgPrint("vconf is registered\n");
554 master_started_cb(NULL, NULL);
560 EAPI int shortcut_icon_service_fini(void)
564 struct pending_item *pend;
566 if (s_info.initialized) {
567 com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
568 s_info.initialized = 0;
575 com_core_packet_client_fini(s_info.fd);
576 s_info.init_cb = NULL;
577 s_info.cbdata = NULL;
580 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
581 s_info.pending_list = dlist_remove(s_info.pending_list, l);
582 packet_unref(pend->packet);
583 if (pend->item->result_cb) {
584 pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
594 EAPI struct shortcut_icon *shortcut_icon_request_create(void)
596 struct shortcut_icon *handle;
598 handle = malloc(sizeof(*handle));
600 ErrPrint("Heap: %s\n", strerror(errno));
604 handle->desc = shortcut_icon_desc_open();
606 ErrPrint("Uanble to open desc\n");
611 handle->state = CREATED;
617 EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
619 if (!handle || handle->state != CREATED) {
620 ErrPrint("Handle is not valid\n");
630 EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
632 if (!handle || handle->state != CREATED) {
633 ErrPrint("Handle is not valid\n");
642 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)
644 if (!handle || handle->state != CREATED) {
645 ErrPrint("Handle is not valid\n");
649 return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
654 EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
656 if (!handle || handle->state != CREATED) {
657 ErrPrint("Handle is not valid\n");
661 (void)shortcut_icon_request_unref(handle);
667 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)
670 struct packet *packet;
671 struct request_item *item;
675 if (!handle || handle->state != CREATED) {
676 ErrPrint("Handle is not valid\n");
681 layout = DEFAULT_ICON_LAYOUT;
685 group = DEFAULT_ICON_GROUP;
688 len = strlen(outfile) + strlen(".desc") + 1;
689 filename = malloc(len);
691 ErrPrint("Heap: %s\n", strerror(errno));
695 snprintf(filename, len, "%s.desc", outfile);
697 ret = shortcut_icon_desc_save(handle->desc, filename);
702 item = malloc(sizeof(*item));
704 ErrPrint("Heap: %s\n", strerror(errno));
705 if (unlink(filename) < 0) {
706 ErrPrint("Unlink: %s\n", strerror(errno));
712 item->result_cb = result_cb;
714 item->handle = shortcut_icon_request_ref(handle);
716 packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
718 ErrPrint("Failed to create a packet\n");
719 if (unlink(filename) < 0) {
720 ErrPrint("Unlink: %s\n", strerror(errno));
723 (void)shortcut_icon_request_unref(handle);
728 if (s_info.fd >= 0 && !s_info.pending_list) {
729 ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
730 packet_destroy(packet);
732 ErrPrint("ret: %d\n", ret);
733 if (unlink(filename) < 0) {
734 ErrPrint("Unlink: %s\n", strerror(errno));
737 (void)shortcut_icon_request_unref(handle);
739 DbgPrint("Request is sent\n");
741 struct pending_item *pend;
743 pend = malloc(sizeof(*pend));
745 ErrPrint("Heap: %s\n", strerror(errno));
746 packet_destroy(packet);
748 if (unlink(filename) < 0) {
749 ErrPrint("Unlink: %s\n", strerror(errno));
751 (void)shortcut_icon_request_unref(handle);
756 pend->packet = packet;
759 s_info.pending_list = dlist_append(s_info.pending_list, pend);
760 DbgPrint("Request is pended\n");