tizen 2.3 release
[apps/livebox/livebox-viewer.git] / dynamicbox_viewer / src / dynamicbox_internal.c
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <fcntl.h>
7
8 #include <dlog.h>
9
10 #include <dynamicbox_errno.h>
11 #include <dynamicbox_service.h>
12 #include <dynamicbox_buffer.h>
13
14 #include <packet.h>
15
16 #include "dlist.h"
17 #include "debug.h"
18 #include "dynamicbox.h"
19 #include "dynamicbox_internal.h"
20 #include "fb.h"
21 #include "conf.h"
22 #include "util.h"
23 #include "master_rpc.h"
24
25 int errno;
26
27 typedef enum event_state {
28     INFO_STATE_CALLBACK_IN_IDLE = 0x00,
29     INFO_STATE_CALLBACK_IN_PROCESSING = 0x01
30 } event_state_e;
31
32 struct event_info {
33     int is_deleted;
34     int (*handler)(dynamicbox_h handler, dynamicbox_event_type_e event, void *data);
35     void *user_data;
36 };
37
38 struct fault_info {
39     int is_deleted;
40     int (*handler)(dynamicbox_fault_type_e event, const char *pkgname, const char *filename, const char *func, void *data);
41     void *user_data;
42 };
43
44 static struct info {
45     struct dlist *dynamicbox_common_list;
46     struct dlist *dynamicbox_list;
47     struct dlist *event_list;
48     struct dlist *fault_list;
49     event_state_e event_state;
50     event_state_e fault_state;
51 } s_info = {
52     .dynamicbox_common_list = NULL,
53     .dynamicbox_list = NULL,
54     .event_list = NULL,
55     .fault_list = NULL,
56     .event_state = INFO_STATE_CALLBACK_IN_IDLE,
57     .fault_state = INFO_STATE_CALLBACK_IN_IDLE,
58 };
59
60 static inline void default_delete_cb(dynamicbox_h handler, int ret, void *data)
61 {
62     DbgPrint("Default deleted event handler: %d\n", ret);
63 }
64
65 static void del_ret_cb(dynamicbox_h handler, const struct packet *result, void *data)
66 {
67     struct cb_info *info = data;
68     int ret;
69     dynamicbox_ret_cb cb;
70     void *cbdata;
71
72     cb = info->cb;
73     cbdata = info->data;
74     dbox_destroy_cb_info(info);
75
76     if (!result) {
77         ErrPrint("Connection lost?\n");
78         ret = DBOX_STATUS_ERROR_FAULT;
79     } else if (packet_get(result, "i", &ret) != 1) {
80         ErrPrint("Invalid argument\n");
81         ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
82     }
83
84     if (ret == 0) {
85         handler->cbs.deleted.cb = cb;
86         handler->cbs.deleted.data = cbdata;
87     } else if (cb) {
88         cb(handler, ret, cbdata);
89     }
90
91     /*!
92      * \note
93      * Do not call the deleted callback from here.
94      * master will send the "deleted" event.
95      * Then invoke this callback.
96      *
97      * if (handler->cbs.deleted.cb)
98      *     handler->cbs.deleted.cb(handler, ret, handler->cbs.deleted.data);
99      */
100 }
101
102 struct dynamicbox_common *dbox_create_common_handle(dynamicbox_h handle, const char *pkgname, const char *cluster, const char *category)
103 {
104     struct dynamicbox_common *common;
105
106     common = calloc(1, sizeof(*common));
107     if (!common) {
108         ErrPrint("Heap: %s\n", strerror(errno));
109         dynamicbox_set_last_status(DBOX_STATUS_ERROR_OUT_OF_MEMORY);
110         return NULL;
111     }
112
113     common->pkgname = strdup(pkgname);
114     if (!common->pkgname) {
115         free(common);
116         dynamicbox_set_last_status(DBOX_STATUS_ERROR_OUT_OF_MEMORY);
117         return NULL;
118     }
119
120     common->cluster = strdup(cluster);
121     if (!common->cluster) {
122         ErrPrint("Error: %s\n", strerror(errno));
123         free(common->pkgname);
124         free(common);
125         dynamicbox_set_last_status(DBOX_STATUS_ERROR_OUT_OF_MEMORY);
126         return NULL;
127     }
128
129     common->category = strdup(category);
130     if (!common->category) {
131         ErrPrint("Error: %s\n", strerror(errno));
132         free(common->cluster);
133         free(common->pkgname);
134         free(common);
135         dynamicbox_set_last_status(DBOX_STATUS_ERROR_OUT_OF_MEMORY);
136         return NULL;
137     }
138
139     /* Data provider will set this */
140     common->dbox.type = DBOX_TYPE_FILE;
141     common->gbar.type = GBAR_TYPE_SCRIPT;
142
143     /* Used for handling the mouse event on a box */
144     common->dbox.mouse_event = 0;
145
146     /* Cluster infomration is not determined yet */
147     common->nr_of_sizes = 0x01;
148
149     common->timestamp = util_timestamp();
150     common->is_user = 1;
151     common->delete_type = DBOX_DELETE_PERMANENTLY;
152
153     common->gbar.lock = NULL;
154     common->gbar.last_extra_buffer_idx = DBOX_UNKNOWN_BUFFER;
155
156     common->dbox.lock = NULL;
157     common->dbox.last_extra_buffer_idx = DBOX_UNKNOWN_BUFFER;
158
159     common->state = DBOX_STATE_CREATE;
160     common->visible = DBOX_SHOW;
161
162     s_info.dynamicbox_common_list = dlist_append(s_info.dynamicbox_common_list, common);
163     return common;
164 }
165
166 int dbox_destroy_common_handle(struct dynamicbox_common *common)
167 {
168     dlist_remove_data(s_info.dynamicbox_common_list, common);
169
170     common->state = DBOX_STATE_DESTROYED;
171
172     if (common->filename) {
173         (void)util_unlink(common->filename);
174     }
175
176     free(common->cluster);
177     free(common->category);
178     free(common->id);
179     free(common->pkgname);
180     free(common->filename);
181     free(common->dbox.auto_launch);
182     free(common->alt.icon);
183     free(common->alt.name);
184
185     if (common->dbox.fb) {
186         fb_destroy(common->dbox.fb);
187         common->dbox.fb = NULL;
188     }
189
190     if (common->gbar.fb) {
191         fb_destroy(common->gbar.fb);
192         common->gbar.fb = NULL;
193     }
194
195     return 0;
196 }
197
198 int dbox_common_ref(struct dynamicbox_common *common, dynamicbox_h handle)
199 {
200     common->dynamicbox_list = dlist_append(common->dynamicbox_list, handle);
201     common->refcnt++;
202
203     return common->refcnt;
204 }
205
206 int dbox_common_unref(struct dynamicbox_common *common, dynamicbox_h handle)
207 {
208     int refcnt;
209     dlist_remove_data(common->dynamicbox_list, handle);
210     refcnt = --common->refcnt;
211
212     return refcnt;
213 }
214
215 int dbox_set_group(struct dynamicbox_common *common, const char *cluster, const char *category)
216 {
217     void *pc = NULL;
218     void *ps = NULL;
219
220     if (cluster) {
221         pc = strdup(cluster);
222         if (!pc) {
223             ErrPrint("Heap: %s (cluster: %s)\n", strerror(errno), cluster);
224             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
225         }
226     }
227
228     if (category) {
229         ps = strdup(category);
230         if (!ps) {
231             ErrPrint("Heap: %s (category: %s)\n", strerror(errno), category);
232             free(pc);
233             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
234         }
235     }
236
237     if (common->cluster) {
238         free(common->cluster);
239     }
240
241     if (common->category) {
242         free(common->category);
243     }
244
245     common->cluster = pc;
246     common->category = ps;
247
248     return DBOX_STATUS_ERROR_NONE;
249 }
250
251 void dbox_set_size(struct dynamicbox_common *common, int w, int h)
252 {
253     int size_type;
254
255     common->dbox.width = w;
256     common->dbox.height = h;
257
258     size_type = dynamicbox_service_size_type(w, h);
259     if (size_type != DBOX_SIZE_TYPE_UNKNOWN) {
260         common->dbox.mouse_event = dynamicbox_service_mouse_event(common->pkgname, size_type);
261     }
262 }
263
264 void dbox_set_update_mode(struct dynamicbox_common *common, int active_mode)
265 {
266     common->is_active_update = active_mode;
267 }
268
269 void dbox_set_gbarsize(struct dynamicbox_common *common, int w, int h)
270 {
271     common->gbar.width = w;
272     common->gbar.height = h;
273 }
274
275 void dbox_set_default_gbarsize(struct dynamicbox_common *common, int w, int h)
276 {
277     common->gbar.default_width = w;
278     common->gbar.default_height = h;
279 }
280
281 void dbox_invoke_fault_handler(dynamicbox_fault_type_e event, const char *pkgname, const char *file, const char *func)
282 {
283     struct dlist *l;
284     struct dlist *n;
285     struct fault_info *info;
286
287     s_info.fault_state = INFO_STATE_CALLBACK_IN_PROCESSING;
288
289     dlist_foreach_safe(s_info.fault_list, l, n, info) {
290         if (!info->is_deleted && info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE) {
291             info->is_deleted = 1;
292         }
293
294         if (info->is_deleted) {
295             s_info.fault_list = dlist_remove(s_info.fault_list, l);
296             free(info);
297         }
298     }
299
300     s_info.fault_state &= ~INFO_STATE_CALLBACK_IN_PROCESSING;
301 }
302
303 void dbox_invoke_event_handler(dynamicbox_h handler, dynamicbox_event_type_e event)
304 {
305     struct dlist *l;
306     struct dlist *n;
307     struct event_info *info;
308
309     if (event == DBOX_EVENT_DBOX_UPDATED && handler->common->refcnt > 1) {
310         if (handler->visible != DBOX_SHOW) {
311             DbgPrint("Update requested(pending) - %s\n", handler->common->pkgname);
312             handler->paused_updating++;
313             return;
314         } else {
315             handler->paused_updating = 0;
316         }
317     }
318
319     s_info.event_state = INFO_STATE_CALLBACK_IN_PROCESSING;
320
321     dlist_foreach_safe(s_info.event_list, l, n, info) {
322         if (!info->is_deleted && info->handler(handler, event, info->user_data) == EXIT_FAILURE) {
323             DbgPrint("Event handler returns EXIT_FAILURE\n");
324             info->is_deleted = 1;
325         }
326
327         if (info->is_deleted) {
328             s_info.event_list = dlist_remove(s_info.event_list, l);
329             free(info);
330         }
331     }
332
333     s_info.event_state &= ~INFO_STATE_CALLBACK_IN_PROCESSING;
334 }
335
336 struct dynamicbox_common *dbox_find_common_handle(const char *pkgname, const char *id)
337 {
338     struct dlist *l;
339     struct dynamicbox_common *common;
340
341     dlist_foreach(s_info.dynamicbox_common_list, l, common) {
342         if (!common->id) {
343             continue;
344         }
345
346         if (!strcmp(common->pkgname, pkgname) && !strcmp(common->id, id)) {
347             return common;
348         }
349     }
350
351     return NULL;
352 }
353
354 struct dynamicbox_common *dbox_find_common_handle_by_timestamp(double timestamp)
355 {
356     struct dlist *l;
357     struct dynamicbox_common *common;
358
359     dlist_foreach(s_info.dynamicbox_common_list, l, common) {
360         if (common->timestamp == timestamp) {
361             return common;
362         }
363     }
364
365     return NULL;
366 }
367
368 dynamicbox_h dbox_new_dynamicbox(const char *pkgname, const char *id, double timestamp, const char *cluster, const char *category)
369 {
370     dynamicbox_h handler;
371
372     handler = calloc(1, sizeof(*handler));
373     if (!handler) {
374         ErrPrint("Failed to create a new dynamicbox\n");
375         return NULL;
376     }
377
378     handler->common = dbox_create_common_handle(handler, pkgname, cluster, category);
379     if (!handler->common) {
380         ErrPrint("Heap: %s\n", strerror(errno));
381         free(handler);
382         return NULL;
383     }
384
385     dbox_common_ref(handler->common, handler);
386     dbox_set_id(handler->common, id);
387     handler->common->timestamp = timestamp;
388     handler->common->state = DBOX_STATE_CREATE;
389     handler->visible = DBOX_SHOW;
390     s_info.dynamicbox_list = dlist_append(s_info.dynamicbox_list, handler);
391
392     return dbox_ref(handler);
393 }
394
395 int dbox_delete_all(void)
396 {
397     struct dlist *l;
398     struct dlist *n;
399     dynamicbox_h handler;
400
401     dlist_foreach_safe(s_info.dynamicbox_list, l, n, handler) {
402         dbox_invoke_event_handler(handler, DBOX_EVENT_DELETED);
403         dbox_unref(handler, 1);
404     }
405
406     return DBOX_STATUS_ERROR_NONE;
407 }
408
409 int dbox_set_content(struct dynamicbox_common *common, const char *content)
410 {
411     char *pc = NULL;
412
413     if (content) {
414         pc = strdup(content);
415         if (!pc) {
416             ErrPrint("heap: %s [%s]\n", strerror(errno), content);
417             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
418         }
419     }
420
421     free(common->content);
422     common->content = pc;
423     return DBOX_STATUS_ERROR_NONE;
424 }
425
426 int dbox_set_title(struct dynamicbox_common *common, const char *title)
427 {
428     char *pt = NULL;
429
430     if (title) {
431         pt = strdup(title);
432         if (!pt) {
433             ErrPrint("heap: %s [%s]\n", strerror(errno), title);
434             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
435         }
436     }
437
438     free(common->title);
439     common->title = pt;
440     return DBOX_STATUS_ERROR_NONE;
441 }
442
443 void dbox_set_size_list(struct dynamicbox_common *common, int size_list)
444 {
445     common->dbox.size_list = size_list;
446 }
447
448 void dbox_set_auto_launch(struct dynamicbox_common *common, const char *auto_launch)
449 {
450     char *pa = NULL;
451
452     if (!auto_launch || !strlen(auto_launch)) {
453         return;
454     }
455
456     pa = strdup(auto_launch);
457     if (!pa) {
458         ErrPrint("heap: %s, [%s]\n", strerror(errno), auto_launch);
459         return;
460     }
461
462     free(common->dbox.auto_launch);
463     common->dbox.auto_launch = pa;
464 }
465
466 void dbox_set_priority(struct dynamicbox_common *common, double priority)
467 {
468     common->dbox.priority = priority;
469 }
470
471 void dbox_set_id(struct dynamicbox_common *common, const char *id)
472 {
473     char *pi = NULL;
474
475     if (id) {
476         pi = strdup(id);
477         if (!pi) {
478             ErrPrint("heap: %s [%s]\n", strerror(errno), pi);
479             return;
480         }
481     }
482
483     free(common->id);
484     common->id = pi;
485 }
486
487 void dbox_unlink_filename(struct dynamicbox_common *common)
488 {
489     if (common->dbox.type == DBOX_TYPE_FILE || common->dbox.type == DBOX_TYPE_TEXT) {
490         if (common->filename && common->filename[0] && unlink(common->filename) < 0) {
491             ErrPrint("unlink: %s (%s)\n", strerror(errno), common->filename);
492         }
493     }
494 }
495
496 void dbox_set_filename(struct dynamicbox_common *common, const char *filename)
497 {
498     if (common->filename) {
499         free(common->filename);
500     }
501
502     common->filename = strdup(filename);
503     if (!common->filename) {
504         ErrPrint("Heap: %s\n", strerror(errno));
505     }
506 }
507
508 void dbox_set_alt_icon(struct dynamicbox_common *common, const char *icon)
509 {
510     char *_icon = NULL;
511
512     if (icon && strlen(icon)) {
513         _icon = strdup(icon);
514         if (!_icon) {
515             ErrPrint("Heap: %s\n", strerror(errno));
516         }
517     }
518
519     free(common->alt.icon);
520     common->alt.icon = _icon;
521 }
522
523 void dbox_set_alt_name(struct dynamicbox_common *common, const char *name)
524 {
525     char *_name = NULL;
526
527     if (name && strlen(name)) {
528         _name = strdup(name);
529         if (!_name) {
530             ErrPrint("Heap: %s\n", strerror(errno));
531         }
532     }
533
534     free(common->alt.name);
535     common->alt.name = _name;
536 }
537
538 int dbox_set_dbox_fb(struct dynamicbox_common *common, const char *filename)
539 {
540     struct fb_info *fb;
541
542     if (!common) {
543         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
544     }
545
546     fb = common->dbox.fb;
547     if (fb && !strcmp(fb_id(fb), filename)) { /*!< BUFFER is not changed, */
548         return DBOX_STATUS_ERROR_NONE;
549     }
550
551     common->dbox.fb = NULL;
552
553     if (!filename || filename[0] == '\0') {
554         if (fb) {
555             fb_destroy(fb);
556         }
557         return DBOX_STATUS_ERROR_NONE;
558     }
559
560     common->dbox.fb = fb_create(filename, common->dbox.width, common->dbox.height);
561     if (!common->dbox.fb) {
562         ErrPrint("Faield to create a FB\n");
563         if (fb) {
564             fb_destroy(fb);
565         }
566         return DBOX_STATUS_ERROR_FAULT;
567     }
568
569     if (fb) {
570         fb_destroy(fb);
571     }
572
573     return DBOX_STATUS_ERROR_NONE;
574 }
575
576 int dbox_set_gbar_fb(struct dynamicbox_common *common, const char *filename)
577 {
578     struct fb_info *fb;
579
580     if (!common || common->state != DBOX_STATE_CREATE) {
581         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
582     }
583
584     fb = common->gbar.fb;
585     if (fb && !strcmp(fb_id(fb), filename)) {
586         /* BUFFER is not changed, just update the content */
587         return DBOX_STATUS_ERROR_EXIST;
588     }
589     common->gbar.fb = NULL;
590
591     if (!filename || filename[0] == '\0') {
592         if (fb) {
593             fb_destroy(fb);
594         }
595         return DBOX_STATUS_ERROR_NONE;
596     }
597
598     common->gbar.fb = fb_create(filename, common->gbar.width, common->gbar.height);
599     if (!common->gbar.fb) {
600         ErrPrint("Failed to create a FB\n");
601         if (fb) {
602             fb_destroy(fb);
603         }
604         return DBOX_STATUS_ERROR_FAULT;
605     }
606
607     if (fb) {
608         fb_destroy(fb);
609     }
610     return DBOX_STATUS_ERROR_NONE;
611 }
612
613 struct fb_info *dbox_get_dbox_fb(struct dynamicbox_common *common)
614 {
615     return common->dbox.fb;
616 }
617
618 struct fb_info *dbox_get_gbar_fb(struct dynamicbox_common *common)
619 {
620     return common->gbar.fb;
621 }
622
623 void dbox_set_user(struct dynamicbox_common *common, int user)
624 {
625     common->is_user = user;
626 }
627
628 void dbox_set_pinup(struct dynamicbox_common *common, int pinup_supported)
629 {
630     common->dbox.pinup_supported = pinup_supported;
631 }
632
633 void dbox_set_text_dbox(struct dynamicbox_common *common)
634 {
635     common->dbox.type = DBOX_TYPE_TEXT;
636 }
637
638 void dbox_set_text_gbar(struct dynamicbox_common *common)
639 {
640     common->gbar.type = GBAR_TYPE_TEXT;
641 }
642
643 int dbox_text_dbox(struct dynamicbox_common *common)
644 {
645     return common->dbox.type == DBOX_TYPE_TEXT;
646 }
647
648 int dbox_text_gbar(struct dynamicbox_common *common)
649 {
650     return common->gbar.type == GBAR_TYPE_TEXT;
651 }
652
653 void dbox_set_period(struct dynamicbox_common *common, double period)
654 {
655     common->dbox.period = period;
656 }
657
658 dynamicbox_h dbox_ref(dynamicbox_h handler)
659 {
660     if (!handler) {
661         return NULL;
662     }
663
664     handler->refcnt++;
665     return handler;
666 }
667
668 dynamicbox_h dbox_unref(dynamicbox_h handler, int destroy_common)
669 {
670     if (!handler) {
671         return NULL;
672     }
673
674     handler->refcnt--;
675     if (handler->refcnt > 0) {
676         return handler;
677     }
678
679     if (handler->cbs.created.cb) {
680         handler->cbs.created.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.created.data);
681         handler->cbs.created.cb = NULL;
682         handler->cbs.created.data = NULL;
683     }
684
685     if (handler->cbs.deleted.cb) {
686         handler->cbs.deleted.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.deleted.data);
687         handler->cbs.deleted.cb = NULL;
688         handler->cbs.deleted.data = NULL;
689     }
690
691     if (handler->cbs.pinup.cb) {
692         handler->cbs.pinup.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.pinup.data);
693         handler->cbs.pinup.cb = NULL;
694         handler->cbs.pinup.data = NULL;
695     }
696
697     if (handler->cbs.group_changed.cb) {
698         handler->cbs.group_changed.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.group_changed.data);
699         handler->cbs.group_changed.cb = NULL;
700         handler->cbs.group_changed.data = NULL;
701     }
702
703     if (handler->cbs.period_changed.cb) {
704         handler->cbs.period_changed.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.period_changed.data);
705         handler->cbs.period_changed.cb = NULL;
706         handler->cbs.period_changed.data = NULL;
707     }
708
709     if (handler->cbs.size_changed.cb) {
710         handler->cbs.size_changed.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.size_changed.data);
711         handler->cbs.size_changed.cb = NULL;
712         handler->cbs.size_changed.data = NULL;
713     }
714
715     if (handler->cbs.gbar_created.cb) {
716         handler->cbs.gbar_created.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.gbar_created.data);
717         handler->cbs.gbar_created.cb = NULL;
718         handler->cbs.gbar_created.data = NULL;
719     }
720
721     if (handler->cbs.gbar_destroyed.cb) {
722         handler->cbs.gbar_destroyed.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.gbar_destroyed.data);
723         handler->cbs.gbar_destroyed.cb = NULL;
724         handler->cbs.gbar_destroyed.data = NULL;
725     }
726
727     if (handler->cbs.update_mode.cb) {
728         handler->cbs.update_mode.cb(handler, DBOX_STATUS_ERROR_FAULT, handler->cbs.update_mode.data);
729         handler->cbs.update_mode.cb = NULL;
730         handler->cbs.update_mode.data = NULL;
731     }
732
733     if (handler->cbs.access_event.cb) {
734         handler->cbs.access_event.cb(handler, DBOX_ACCESS_STATUS_ERROR, handler->cbs.access_event.data);
735         handler->cbs.access_event.cb = NULL;
736         handler->cbs.access_event.data = NULL;
737     }
738
739     if (handler->cbs.key_event.cb) {
740         handler->cbs.key_event.cb(handler, DBOX_KEY_STATUS_ERROR, handler->cbs.key_event.data);
741         handler->cbs.key_event.cb = NULL;
742         handler->cbs.key_event.data = NULL;
743     }
744
745     dlist_remove_data(s_info.dynamicbox_list, handler);
746
747     handler->state = DBOX_STATE_DESTROYED;
748     if (dbox_common_unref(handler->common, handler) == 0) {
749         if (destroy_common) {
750             /*!
751              * \note
752              * Lock file should be deleted after all callbacks are processed.
753              */
754             (void)dynamicbox_service_destroy_lock(handler->common->dbox.lock);
755             handler->common->dbox.lock = NULL;
756             dbox_destroy_common_handle(handler->common);
757         }
758     }
759     free(handler);
760     DbgPrint("Handler is released\n");
761     return NULL;
762 }
763
764 int dbox_send_delete(dynamicbox_h handler, int type, dynamicbox_ret_cb cb, void *data)
765 {
766     struct packet *packet;
767     struct cb_info *cbinfo;
768     int ret;
769
770     if (handler->common->request.deleted) {
771         ErrPrint("Already in-progress\n");
772         if (cb) {
773             cb(handler, DBOX_STATUS_ERROR_NONE, data);
774         }
775         return DBOX_STATUS_ERROR_BUSY;
776     }
777
778     if (!cb) {
779         cb = default_delete_cb;
780     }
781
782     packet = packet_create("delete", "ssid", handler->common->pkgname, handler->common->id, type, handler->common->timestamp);
783     if (!packet) {
784         ErrPrint("Failed to build a param\n");
785         if (cb) {
786             cb(handler, DBOX_STATUS_ERROR_FAULT, data);
787         }
788
789         return DBOX_STATUS_ERROR_FAULT;
790     }
791
792     cbinfo = dbox_create_cb_info(cb, data);
793     if (!cbinfo) {
794         packet_destroy(packet);
795         ErrPrint("Failed to create cbinfo\n");
796         if (cb) {
797             cb(handler, DBOX_STATUS_ERROR_FAULT, data);
798         }
799
800         return DBOX_STATUS_ERROR_FAULT;
801     }
802
803     ret = master_rpc_async_request(handler, packet, 0, del_ret_cb, cbinfo);
804     if (ret < 0) {
805         /*!
806          * Packet is destroyed by master_rpc_async_request.
807          */
808         dbox_destroy_cb_info(cbinfo);
809
810         if (cb) {
811             cb(handler, DBOX_STATUS_ERROR_FAULT, data);
812         }
813     } else {
814         handler->common->request.deleted = 1;
815     }
816
817     return ret;
818 }
819
820 int dbox_sync_dbox_fb(struct dynamicbox_common *common)
821 {
822     int ret;
823
824     if (fb_type(dbox_get_dbox_fb(common)) == DBOX_FB_TYPE_FILE) {
825         (void)dynamicbox_service_acquire_lock(common->dbox.lock);
826         ret = fb_sync(dbox_get_dbox_fb(common), common->dbox.last_damage.x, common->dbox.last_damage.y, common->dbox.last_damage.w, common->dbox.last_damage.h);
827         (void)dynamicbox_service_release_lock(common->dbox.lock);
828     } else {
829         ret = fb_sync(dbox_get_dbox_fb(common), common->dbox.last_damage.x, common->dbox.last_damage.y, common->dbox.last_damage.w, common->dbox.last_damage.h);
830     }
831
832     return ret;
833 }
834
835 int dbox_sync_gbar_fb(struct dynamicbox_common *common)
836 {
837     int ret;
838
839     if (fb_type(dbox_get_gbar_fb(common)) == DBOX_FB_TYPE_FILE) {
840         (void)dynamicbox_service_acquire_lock(common->gbar.lock);
841         ret = fb_sync(dbox_get_gbar_fb(common), common->gbar.last_damage.x, common->gbar.last_damage.y, common->gbar.last_damage.w, common->gbar.last_damage.h);
842         (void)dynamicbox_service_release_lock(common->gbar.lock);
843     } else {
844         ret = fb_sync(dbox_get_gbar_fb(common), common->gbar.last_damage.x, common->gbar.last_damage.y, common->gbar.last_damage.w, common->gbar.last_damage.h);
845     }
846
847     return ret;
848 }
849
850 struct dynamicbox_common *dbox_find_sharable_common_handle(const char *pkgname, const char *content, int w, int h, const char *cluster, const char *category)
851 {
852     struct dlist *l;
853     struct dynamicbox_common *common;
854
855     if (!conf_shared_content()) {
856         /*!
857          * Shared content option is turnned off.
858          */
859         return NULL;
860     }
861
862     dlist_foreach(s_info.dynamicbox_common_list, l, common) {
863         if (common->state != DBOX_STATE_CREATE) {
864             continue;
865         }
866
867         if (strcmp(common->pkgname, pkgname)) {
868             continue;
869         }
870
871         if (strcmp(common->cluster, cluster)) {
872             DbgPrint("Cluster mismatched\n");
873             continue;
874         }
875
876         if (strcmp(common->category, category)) {
877             DbgPrint("Category mismatched\n");
878             continue;
879         }
880
881         if (common->content && content) {
882             if (strcmp(common->content, content)) {
883                 DbgPrint("%s Content ([%s] <> [%s])\n", common->pkgname, common->content, content);
884                 continue;    
885             }
886         } else {
887             int c1_len;
888             int c2_len;
889
890             /*!
891              * \note
892              * We assumes "" (ZERO length string) to NULL
893              */
894             c1_len = common->content ? strlen(common->content) : 0;
895             c2_len = content ? strlen(content) : 0;
896             if (c1_len != c2_len) {
897                 DbgPrint("%s Content %p <> %p\n", common->pkgname, common->content, content);
898                 continue;
899             }
900         }
901
902         if (common->request.size_changed) {
903             DbgPrint("Changing size\n");
904             /*!
905              * \note
906              * Do not re-use resizing instance.
907              * We will not use predicted size.
908              */
909             continue;
910         }
911
912         if (common->request.created) {
913             DbgPrint("Creating now but re-use it (%s)\n", common->pkgname);
914         }
915
916         if (common->dbox.width != w || common->dbox.height != h) {
917             DbgPrint("Size mismatched\n");
918             continue;
919         }
920
921         DbgPrint("common handle is found: %p\n", common);
922         return common;
923     }
924
925     return NULL;
926 }
927
928 dynamicbox_h dbox_find_dbox_in_show(struct dynamicbox_common *common)
929 {
930     struct dlist *l;
931     dynamicbox_h item;
932
933     dlist_foreach(common->dynamicbox_list, l, item) {
934         if (item->visible == DBOX_SHOW) {
935             DbgPrint("%s visibility is not changed\n", common->pkgname);
936             return item;
937         }
938     }
939
940     return NULL;
941 }
942
943 dynamicbox_h dbox_get_dbox_nth(struct dynamicbox_common *common, int nth)
944 {
945     dynamicbox_h item;
946     struct dlist *l;
947
948     l = dlist_nth(common->dynamicbox_list, nth);
949     item = dlist_data(l);
950
951     return item;
952 }
953
954 int dbox_add_event_handler(dynamicbox_event_handler_cb dbox_cb, void *data)
955 {
956     struct event_info *info;
957     info = malloc(sizeof(*info));
958     if (!info) {
959         ErrPrint("Heap: %s\n", strerror(errno));
960         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
961     }
962
963     info->handler = dbox_cb;
964     info->user_data = data;
965     info->is_deleted = 0;
966
967     s_info.event_list = dlist_append(s_info.event_list, info);
968     return DBOX_STATUS_ERROR_NONE;
969 }
970
971 void *dbox_remove_event_handler(dynamicbox_event_handler_cb dbox_cb)
972 {
973     struct event_info *info;
974     struct dlist *l;
975
976     dlist_foreach(s_info.event_list, l, info) {
977         if (info->handler == dbox_cb) {
978             void *data;
979
980             data = info->user_data;
981
982             if (s_info.event_state == INFO_STATE_CALLBACK_IN_PROCESSING) {
983                 info->is_deleted = 1;
984             } else {
985                 s_info.event_list = dlist_remove(s_info.event_list, l);
986                 free(info);
987             }
988
989             return data;
990         }
991     }
992
993     return NULL;
994 }
995
996 int dbox_add_fault_handler(dynamicbox_fault_handler_cb dbox_cb, void *data)
997 {
998     struct fault_info *info;
999     info = malloc(sizeof(*info));
1000     if (!info) {
1001         ErrPrint("Heap: %s\n", strerror(errno));
1002         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1003     }
1004
1005     info->handler = dbox_cb;
1006     info->user_data = data;
1007     info->is_deleted = 0;
1008
1009     s_info.fault_list = dlist_append(s_info.fault_list, info);
1010     return DBOX_STATUS_ERROR_NONE;
1011 }
1012
1013 void *dbox_remove_fault_handler(dynamicbox_fault_handler_cb dbox_cb)
1014 {
1015     struct fault_info *info;
1016     struct dlist *l;
1017
1018     dlist_foreach(s_info.fault_list, l, info) {
1019         if (info->handler == dbox_cb) {
1020             void *data;
1021
1022             data = info->user_data;
1023
1024             if (s_info.fault_state == INFO_STATE_CALLBACK_IN_PROCESSING) {
1025                 info->is_deleted = 1;
1026             } else {
1027                 s_info.fault_list = dlist_remove(s_info.fault_list, l);
1028                 free(info);
1029             }
1030
1031             return data;
1032         }
1033     }
1034
1035     return NULL;
1036 }
1037
1038 struct cb_info *dbox_create_cb_info(dynamicbox_ret_cb cb, void *data)
1039 {
1040     struct cb_info *info;
1041
1042     info = malloc(sizeof(*info));
1043     if (!info) {
1044         ErrPrint("Heap: %s\n", strerror(errno));
1045         return NULL;
1046     }
1047
1048     info->cb = cb;
1049     info->data = data;
1050     return info;
1051 }
1052
1053 void dbox_destroy_cb_info(struct cb_info *info)
1054 {
1055     free(info);
1056 }
1057
1058 /* End of a file */