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.
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
31 #include <vconf-keys.h>
35 #include <com-core_packet.h>
37 #include "shortcut_internal.h"
43 #define CREATED 0x00BEEF00
44 #define DESTROYED 0x00DEAD00
49 int (*init_cb)(int status, void *data);
53 const char *utility_socket;
55 struct dlist *pending_list;
62 .utility_socket = "/tmp/.utility.service",
69 struct shortcut_icon *handle;
70 icon_request_cb_t result_cb;
77 struct request_item *item;
78 struct packet *packet;
96 struct shortcut_icon {
98 struct shortcut_desc *desc;
105 struct shortcut_desc {
108 unsigned int last_idx;
110 struct dlist *block_list;
115 static inline void delete_block(struct block *block)
117 DbgPrint("Release block: %p\n", block);
123 free(block->target_id);
129 static inline int shortcut_icon_desc_close(struct shortcut_desc *handle)
135 dlist_foreach_safe(handle->block_list, l, n, block) {
136 handle->block_list = dlist_remove(handle->block_list, l);
146 static inline struct shortcut_icon *shortcut_icon_request_unref(struct shortcut_icon *handle)
149 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
151 if (handle->refcnt == 0) {
152 handle->state = DESTROYED;
153 shortcut_icon_desc_close(handle->desc);
163 static inline struct shortcut_icon *shortcut_icon_request_ref(struct shortcut_icon *handle)
166 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
172 static int disconnected_cb(int handle, void *data)
174 if (s_info.fd != handle) {
178 ErrPrint("Disconnected\n");
180 s_info.init_cb = NULL;
181 s_info.cbdata = NULL;
182 s_info.initialized = 0;
188 static inline struct shortcut_desc *shortcut_icon_desc_open(void)
190 struct shortcut_desc *handle;
192 handle = calloc(1, sizeof(*handle));
194 ErrPrint("Error: %s\n", strerror(errno));
203 static inline int shortcut_icon_desc_save(struct shortcut_desc *handle, const char *filename)
214 fp = fopen(filename, "w+t");
216 ErrPrint("Error: %s\n", strerror(errno));
220 DbgPrint("Close and flush\n");
221 dlist_foreach_safe(handle->block_list, l, n, block) {
225 fprintf(fp, "type=%s\n", block->type);
226 DbgPrint("type=%s\n", block->type);
230 fprintf(fp, "part=%s\n", block->part);
231 DbgPrint("part=%s\n", block->part);
235 fprintf(fp, "data=%s\n", block->data);
236 DbgPrint("data=%s\n", block->data);
240 fprintf(fp, "option=%s\n", block->option);
241 DbgPrint("option=%s\n", block->option);
245 fprintf(fp, "id=%s\n", block->id);
246 DbgPrint("id=%s\n", block->id);
249 if (block->target_id) {
250 fprintf(fp, "target=%s\n", block->target_id);
251 DbgPrint("target=%s\n", block->target_id);
258 if (fclose(fp) != 0) {
259 ErrPrint("fclose: %s\n", strerror(errno));
266 static inline struct block *find_block(struct shortcut_desc *handle, const char *id, const char *part)
271 dlist_foreach(handle->block_list, l, block) {
272 if (!strcmp(block->part, part) && (!id || !strcmp(block->id, id))) {
282 static inline int update_block(struct block *block, const char *data, const char *option)
285 char *_option = NULL;
288 _data = strdup(data);
290 ErrPrint("Heap: %s\n", strerror(errno));
296 _option = strdup(option);
298 ErrPrint("Heap: %s\n", strerror(errno));
307 block->option = _option;
319 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)
323 if (!handle || !type) {
324 return SHORTCUT_ERROR_INVALID;
336 if (strcmp(type, SHORTCUT_ICON_TYPE_SCRIPT)) {
337 ErrPrint("target id only can be used for script type\n");
342 block = find_block(handle, id, part);
344 block = calloc(1, sizeof(*block));
346 ErrPrint("Heap: %s\n", strerror(errno));
347 return SHORTCUT_ERROR_MEMORY;
350 block->type = strdup(type);
352 ErrPrint("Heap: %s\n", strerror(errno));
354 return SHORTCUT_ERROR_MEMORY;
357 block->part = strdup(part);
359 ErrPrint("Heap: %s\n", strerror(errno));
362 return SHORTCUT_ERROR_MEMORY;
365 block->data = strdup(data);
367 ErrPrint("Heap: %s\n", strerror(errno));
371 return SHORTCUT_ERROR_MEMORY;
375 block->option = strdup(option);
376 if (!block->option) {
377 ErrPrint("Heap: %s\n", strerror(errno));
382 return SHORTCUT_ERROR_MEMORY;
387 block->id = strdup(id);
389 ErrPrint("Heap: %s\n", strerror(errno));
395 return SHORTCUT_ERROR_MEMORY;
400 block->target_id = strdup(target_id);
401 if (!block->target_id) {
402 ErrPrint("Heap: %s\n", strerror(errno));
409 return SHORTCUT_ERROR_MEMORY;
413 block->idx = handle->last_idx++;
414 handle->block_list = dlist_append(handle->block_list, block);
416 if (strcmp(block->type, type)) {
417 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
421 if ((block->target_id && !target_id) || (!block->target_id && target_id)) {
422 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
426 if (block->target_id && target_id && strcmp(block->target_id, target_id)) {
427 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
431 update_block(block, data, option);
439 static int icon_request_cb(pid_t pid, int handle, const struct packet *packet, void *data)
441 struct request_item *item = data;
446 DbgPrint("Disconnected?\n");
448 if (packet_get(packet, "i", &ret) != 1) {
449 DbgPrint("Invalid packet\n");
454 if (item->result_cb) {
455 item->result_cb(item->handle, ret, item->data);
458 (void)shortcut_icon_request_unref(item->handle);
465 static inline int make_connection(void)
468 static struct method service_table[] = {
475 s_info.fd = com_core_packet_client_init(s_info.utility_socket, 0, service_table);
477 ret = SHORTCUT_ERROR_COMM;
479 if (s_info.init_cb) {
480 s_info.init_cb(ret, s_info.cbdata);
485 struct pending_item *pend;
487 if (s_info.init_cb) {
488 s_info.init_cb(SHORTCUT_SUCCESS, s_info.cbdata);
491 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
492 s_info.pending_list = dlist_remove(s_info.pending_list, l);
494 ret = com_core_packet_async_send(s_info.fd, pend->packet, 0.0f, icon_request_cb, pend->item);
495 packet_destroy(pend->packet);
497 ErrPrint("ret: %d\n", ret);
498 if (pend->item->result_cb) {
499 pend->item->result_cb(pend->item->handle, ret, pend->item->data);
507 ret = SHORTCUT_SUCCESS;
515 static void master_started_cb(keynode_t *node, void *user_data)
519 if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0) {
520 ErrPrint("Unable to get \"%s\"\n", VCONFKEY_MASTER_STARTED);
523 if (state == 1 && make_connection() == SHORTCUT_SUCCESS) {
525 ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
526 DbgPrint("Ignore VCONF [%d]\n", ret);
532 EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
536 if (s_info.fd >= 0) {
540 if (s_info.initialized) {
541 s_info.initialized = 1;
542 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
545 s_info.init_cb = init_cb;
546 s_info.cbdata = data;
548 ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
550 ErrPrint("Failed to add vconf for service state [%d]\n", ret);
552 DbgPrint("vconf is registered\n");
555 master_started_cb(NULL, NULL);
561 EAPI int shortcut_icon_service_fini(void)
565 struct pending_item *pend;
567 if (s_info.initialized) {
568 com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
569 s_info.initialized = 0;
576 com_core_packet_client_fini(s_info.fd);
577 s_info.init_cb = NULL;
578 s_info.cbdata = NULL;
581 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
582 s_info.pending_list = dlist_remove(s_info.pending_list, l);
583 packet_unref(pend->packet);
584 if (pend->item->result_cb) {
585 pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
595 EAPI struct shortcut_icon *shortcut_icon_request_create(void)
597 struct shortcut_icon *handle;
599 handle = malloc(sizeof(*handle));
601 ErrPrint("Heap: %s\n", strerror(errno));
605 handle->desc = shortcut_icon_desc_open();
607 ErrPrint("Uanble to open desc\n");
612 handle->state = CREATED;
618 EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
620 if (!handle || handle->state != CREATED) {
621 ErrPrint("Handle is not valid\n");
631 EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
633 if (!handle || handle->state != CREATED) {
634 ErrPrint("Handle is not valid\n");
643 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)
645 if (!handle || handle->state != CREATED) {
646 ErrPrint("Handle is not valid\n");
650 return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
655 EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
657 if (!handle || handle->state != CREATED) {
658 ErrPrint("Handle is not valid\n");
662 (void)shortcut_icon_request_unref(handle);
668 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)
671 struct packet *packet;
672 struct request_item *item;
677 if (!handle || handle->state != CREATED) {
678 ErrPrint("Handle is not valid\n");
683 layout = DEFAULT_ICON_LAYOUT;
687 group = DEFAULT_ICON_GROUP;
690 len = strlen(outfile) + strlen(".desc") + 1 + 30; /* 30 == strlen(tv.tv_sec) + strlen(tv.tv_usec) + 10 (reserved) */
691 filename = malloc(len);
693 ErrPrint("Heap: %s\n", strerror(errno));
697 if (gettimeofday(&tv, NULL) != 0) {
698 ErrPrint("gettimeofday: %s\n", strerror(errno));
703 ret = snprintf(filename, len, "%s.%lu.%lu.desc", outfile, tv.tv_sec, tv.tv_usec);
705 ErrPrint("snprintf: %s\n", strerror(errno));
709 ret = shortcut_icon_desc_save(handle->desc, filename);
714 item = malloc(sizeof(*item));
716 ErrPrint("Heap: %s\n", strerror(errno));
717 if (unlink(filename) < 0) {
718 ErrPrint("Unlink: %s\n", strerror(errno));
724 item->result_cb = result_cb;
726 item->handle = shortcut_icon_request_ref(handle);
728 packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
730 ErrPrint("Failed to create a packet\n");
731 if (unlink(filename) < 0) {
732 ErrPrint("Unlink: %s\n", strerror(errno));
735 (void)shortcut_icon_request_unref(handle);
740 if (s_info.fd >= 0 && !s_info.pending_list) {
741 ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
742 packet_destroy(packet);
744 ErrPrint("ret: %d\n", ret);
745 if (unlink(filename) < 0) {
746 ErrPrint("Unlink: %s\n", strerror(errno));
749 (void)shortcut_icon_request_unref(handle);
751 DbgPrint("Request is sent\n");
753 struct pending_item *pend;
755 pend = malloc(sizeof(*pend));
757 ErrPrint("Heap: %s\n", strerror(errno));
758 packet_destroy(packet);
760 if (unlink(filename) < 0) {
761 ErrPrint("Unlink: %s\n", strerror(errno));
763 (void)shortcut_icon_request_unref(handle);
768 pend->packet = packet;
771 s_info.pending_list = dlist_append(s_info.pending_list, pend);
772 DbgPrint("Request is pended\n");