Supporting the easy mode livebox icon generating service.
[platform/framework/web/data-provider-slave.git] / src / lb.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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
7  *
8  * http://floralicense.org/license/
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h> /* exit */
19 #include <errno.h>
20 #include <unistd.h> /* access */
21
22 #include <Ecore.h>
23 #include <Eina.h>
24
25 #include <dlog.h>
26 #include <provider.h>
27 #include <livebox.h>
28 #include <livebox-errno.h>
29
30 #include "critical_log.h"
31 #include "debug.h"
32 #include "conf.h"
33 #include "so_handler.h"
34 #include "lb.h"
35 #include "update_monitor.h"
36 #include "fault.h"
37 #include "util.h"
38
39 #define IS_LB_SHOWN(itm) (!(itm)->inst->item->has_livebox_script || ((itm)->inst->item->has_livebox_script && (itm)->is_lb_show))
40
41 int errno;
42
43 #define UPDATE_ITEM_DELETED     (-1)
44 #define UPDATE_INVOKED          (-2)
45 #define UPDATE_NOT_INVOKED      (0)
46
47 struct item {
48         Ecore_Timer *timer;
49         struct instance *inst;
50         int monitor_cnt;
51         Ecore_Timer *monitor;
52         int deleteme;
53         double update_interval;
54         int heavy_updating; /* Only for debugging message */
55         int is_paused; /* 1 is paused, 0 is resumed */
56         double sleep_at;
57
58         unsigned int updated_in_pause;
59
60         int is_lb_show;
61         int is_pd_show;
62         int is_lb_updated;
63 };
64
65 static struct info {
66         Eina_List *item_list;
67         struct item *update;
68         Eina_List *pending_list;
69         Ecore_Timer *pending_timer;
70         Eina_List *pd_open_pending_list;
71         Ecore_Timer *pd_open_pending_timer;
72         int paused;
73         Eina_List *pd_list;
74         int secured;
75         int pending_timer_freezed;
76 } s_info  = {
77         .item_list = NULL,
78         .update = NULL,
79         .pending_list = NULL,
80         .pending_timer = NULL,
81         .pd_open_pending_list = NULL,
82         .pd_open_pending_timer = NULL,
83         .paused = 0,
84         .pd_list = NULL,
85         .secured = 0,
86         .pending_timer_freezed = 0,
87 };
88
89 static Eina_Bool updator_cb(void *data);
90
91 static void pending_timer_freeze(void)
92 {
93         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
94         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
95                 DbgPrint("Freeze the pending timer\n");
96                 ecore_timer_freeze(s_info.pending_timer);
97         }
98
99         s_info.pending_timer_freezed++;
100 }
101
102 static void pending_timer_thaw(void)
103 {
104         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
105         if (!s_info.pending_timer_freezed)
106                 return;
107
108         s_info.pending_timer_freezed--;
109         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
110                 DbgPrint("Thaw the pending timer\n");
111                 ecore_timer_thaw(s_info.pending_timer);
112         }
113 }
114
115 /*
116  * -1 : PD is opened, but not mine
117  *  0 : PD is not opened
118  *  1 : my PD is opened
119  */
120 static inline int pd_is_opened(const char *pkgname)
121 {
122         int i;
123         Eina_List *l;
124         char *tmp;
125
126         i = 0;
127         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
128                 if (pkgname && !strcmp(pkgname, tmp))
129                         return 1;
130
131                 i++;
132         }
133
134         return i > 0 ? -1 : 0;
135 }
136
137 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
138 {
139         struct item *item;
140
141         item = eina_list_nth(s_info.pd_open_pending_list, 0);
142         if (!item)
143                 goto cleanout;
144
145         if (s_info.update)
146                 return ECORE_CALLBACK_RENEW;
147
148         s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
149         /*!
150          * \note
151          * To prevent from checking the is_updated function
152          */
153         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
154                 /* Item is destroyed */
155         }
156
157         if (s_info.pd_open_pending_list)
158                 return ECORE_CALLBACK_RENEW;
159
160 cleanout:
161         s_info.pd_open_pending_timer = NULL;
162         return ECORE_CALLBACK_CANCEL;
163 }
164
165 static Eina_Bool pended_cmd_consumer_cb(void *data)
166 {
167         struct item *item;
168
169         item = eina_list_nth(s_info.pending_list, 0);
170         if (!item)
171                 goto cleanout;
172
173         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0)
174                 return ECORE_CALLBACK_RENEW;
175
176         s_info.pending_list = eina_list_remove(s_info.pending_list, item);
177         /*!
178          * \note
179          * To prevent from checking the is_updated function
180          */
181         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
182                 /* item is destroyed */
183         }
184
185         if (s_info.pending_list)
186                 return ECORE_CALLBACK_RENEW;
187
188 cleanout:
189         s_info.pending_timer = NULL;
190         s_info.pending_timer_freezed = 0;
191         return ECORE_CALLBACK_CANCEL;
192 }
193
194 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
195 {
196         if (s_info.pending_timer)
197                 return 0;
198
199         s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
200         if (!s_info.pending_timer) {
201                 ErrPrint("Failed to add a new pended command consumer\n");
202                 return LB_STATUS_ERROR_FAULT;
203         }
204
205         /*!
206          * Do not increase the freezed counter.
207          * Just freeze the timer.
208          */
209         if (s_info.pending_timer_freezed)
210                 ecore_timer_freeze(s_info.pending_timer);
211
212         return 0;
213 }
214
215 static inline void deactivate_pending_consumer(void)
216 {
217         if (!s_info.pending_timer)
218                 return;
219
220         ecore_timer_del(s_info.pending_timer);
221         s_info.pending_timer = NULL;
222         s_info.pending_timer_freezed = 0;
223 }
224
225 static inline void deactivate_pd_open_pending_consumer(void)
226 {
227         if (!s_info.pd_open_pending_timer)
228                 return;
229
230         ecore_timer_del(s_info.pd_open_pending_timer);
231         s_info.pd_open_pending_timer = NULL;
232 }
233
234 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
235 {
236         if (s_info.pd_open_pending_timer)
237                 return 0;
238
239         s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
240         if (!s_info.pd_open_pending_timer) {
241                 ErrPrint("Failed to add a new pended command consumer\n");
242                 return LB_STATUS_ERROR_FAULT;
243         }
244
245         return 0;
246 }
247
248 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
249 {
250         Eina_List *l;
251         Eina_List *n;
252         struct item *item;
253         int cnt = 0;
254
255         EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
256                 if (strcmp(pkgname, item->inst->item->pkgname))
257                         continue;
258
259                 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
260                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
261                 cnt++;
262         }
263
264         if (s_info.pd_open_pending_list)
265                 activate_pd_open_pending_consumer();
266
267         if (!s_info.pending_list)
268                 deactivate_pending_consumer();
269 }
270
271 static inline void migrate_to_pending_list(const char *pkgname)
272 {
273         Eina_List *l;
274         Eina_List *n;
275         struct item *item;
276         int cnt = 0;
277
278         EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
279                 if (strcmp(pkgname, item->inst->item->pkgname))
280                         continue;
281
282                 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
283                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
284                 cnt++;
285         }
286
287         if (s_info.pending_list)
288                 activate_pending_consumer();
289
290         if (!s_info.pd_open_pending_list)
291                 deactivate_pd_open_pending_consumer();
292 }
293
294 static inline int is_pended_item(struct item *item)
295 {
296         struct item *in_item;
297         if (pd_is_opened(item->inst->item->pkgname) == 1) {
298                 in_item = eina_list_data_find(s_info.pd_open_pending_list, item);
299         } else {
300                 in_item = eina_list_data_find(s_info.pending_list, item);
301         }
302
303         return (in_item == item);
304 }
305
306 static int append_pending_list(struct item *item)
307 {
308         if (pd_is_opened(item->inst->item->pkgname) == 1) {
309                 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
310                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
311                         return LB_STATUS_ERROR_EXIST;
312                 }
313
314                 if (activate_pd_open_pending_consumer() < 0) {
315                         ErrPrint("Failed to activate PD open pending consumer\n");
316                         return LB_STATUS_ERROR_FAULT;
317                 }
318
319                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
320         } else {
321                 if (eina_list_data_find(s_info.pending_list, item) == item) {
322                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
323                         return LB_STATUS_ERROR_EXIST;
324                 }
325
326                 if (activate_pending_consumer() < 0)
327                         return LB_STATUS_ERROR_FAULT;
328
329                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
330         }
331         return 0;
332 }
333
334 /*!
335  * \brief
336  *   This function can call the update callback
337  * return 0 if there is no changes
338  * return -1 the item is deleted
339  */
340 static inline int timer_thaw(struct item *item)
341 {
342         double pending;
343         double period;
344         double delay;
345         double sleep_time;
346
347         if (!item->timer)
348                 return 0;
349
350         ecore_timer_thaw(item->timer);
351         period = ecore_timer_interval_get(item->timer);
352         pending = ecore_timer_pending_get(item->timer);
353         delay = util_time_delay_for_compensation(period) - pending;
354         ecore_timer_delay(item->timer, delay);
355
356         if (item->sleep_at == 0.0f)
357                 return 0;
358
359         sleep_time = util_timestamp() - item->sleep_at;
360         item->sleep_at = 0.0f;
361
362         if (sleep_time > pending) {
363                 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
364                         /* item is destroyed */
365                         return UPDATE_ITEM_DELETED;
366                 } else {
367                         return UPDATE_INVOKED;
368                 }
369         }
370
371         return UPDATE_NOT_INVOKED;
372 }
373
374 static inline void timer_freeze(struct item *item)
375 {
376         struct timeval tv;
377
378         if (!item->timer)
379                 return;
380
381         ecore_timer_freeze(item->timer);
382
383         if (ecore_timer_interval_get(item->timer) <= 1.0f)
384                 return;
385
386         if (gettimeofday(&tv, NULL) < 0) {
387                 ErrPrint("gettimeofday: %s\n", strerror(errno));
388                 tv.tv_sec = 0;
389                 tv.tv_usec = 0;
390         }
391
392         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
393 }
394
395 static inline void update_monitor_cnt(struct item *item)
396 {
397         double now;
398         double interval;
399
400         now = util_timestamp();
401         interval = now - item->update_interval;
402
403         /*!
404          * \note
405          * If the content update is processed in too short time,
406          * don't increase the monitor counter, instead of it
407          * set the heavy updating flag.
408          * And handling this heavy updating from the
409          * file update callback.
410          */
411         if (interval >= MINIMUM_UPDATE_INTERVAL) {
412                 if (s_info.update == item) {
413                         /*!
414                          * \note
415                          * If already in updating mode,
416                          * reset the monitor_cnt to 1,
417                          * all updated event will be merged into A inotify event
418                          */
419                         DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
420                         item->monitor_cnt = 1;
421                 } else {
422                         item->monitor_cnt++;
423                 }
424         } else {
425                 item->heavy_updating = 1;
426         }
427
428         item->update_interval = now;
429 }
430
431 static inline Eina_List *find_item(struct instance *inst)
432 {
433         Eina_List *l;
434         struct item *item;
435         
436         EINA_LIST_FOREACH(s_info.item_list, l, item) {
437                 if (item->inst == inst)
438                         return l;
439         }
440
441         return NULL;
442 }
443
444 static inline int output_handler(struct item *item)
445 {
446         int invalid = 0;
447
448         item->monitor_cnt--;
449         if (item->monitor_cnt < 0 || item->heavy_updating) {
450                 if (!item->heavy_updating) {
451                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
452                         invalid = 1;
453                 } else {
454                         item->heavy_updating = 0;       /* Reset flag */
455                 }
456
457                 item->monitor_cnt = 0;
458         }
459
460         if (item->monitor_cnt == 0) {
461                 if (!invalid)
462                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
463
464                 if (item->monitor) {
465                         ecore_timer_del(item->monitor);
466                         item->monitor = NULL;
467                 }
468
469                 if (s_info.update == item)
470                         s_info.update = NULL;
471
472                 if (item->deleteme) {
473                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
474                         (void)so_destroy(item->inst);
475                         free(item);
476                         return EXIT_FAILURE;
477                 }
478         }
479
480         return EXIT_SUCCESS;
481 }
482
483 static int desc_updated_cb(const char *filename, void *data, int over)
484 {
485         struct item *item;
486
487         if (over)
488                 WarnPrint("Event Q overflow\n");
489
490         item = data;
491
492         DbgPrint("DESC %s is updated\n", filename);
493         if (item->is_pd_show) {
494                 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
495         } else {
496                 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
497         }
498         return EXIT_SUCCESS;
499 }
500
501 static int file_updated_cb(const char *filename, void *data, int over)
502 {
503         struct item *item;
504         int w;
505         int h;
506         double priority;
507         char *content = NULL;
508         char *title = NULL;
509         int ret;
510
511         if (over)
512                 WarnPrint("Event Q overflow\n");
513
514         item = data;
515
516         ret = util_get_filesize(filename);
517         if (ret <= 0) {
518                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
519                 return EXIT_SUCCESS; /*!< To keep the callback */
520         }
521
522         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
523         if (ret < 0) {
524                 ErrPrint("livebox_get_info returns %d\n", ret);
525                 return EXIT_SUCCESS; /*!< To keep the callback */
526         }
527
528         if (IS_LB_SHOWN(item)) {
529                 provider_send_updated(item->inst->item->pkgname, item->inst->id,
530                                         item->inst->w, item->inst->h, item->inst->priority,
531                                         content, title);
532         } else {
533                 item->is_lb_updated++;
534         }
535
536         return output_handler(item);
537 }
538
539 static void reset_lb_updated_flag(struct item *item)
540 {
541         if (!item->is_lb_updated)
542                 return;
543
544         DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
545                         item->inst->id, item->is_lb_updated,
546                         item->inst->content, item->inst->title);
547
548         provider_send_updated(item->inst->item->pkgname, item->inst->id,
549                         item->inst->w, item->inst->h, item->inst->priority,
550                         item->inst->content, item->inst->title);
551
552         item->is_lb_updated = 0;
553 }
554
555 static inline int clear_from_pd_open_pending_list(struct item *item)
556 {
557         Eina_List *l;
558         struct item *tmp;
559
560         EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
561                 if (tmp != item)
562                         continue;
563
564                 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
565                 if (!s_info.pd_open_pending_list)
566                         deactivate_pd_open_pending_consumer();
567                 return LB_STATUS_SUCCESS;
568         }
569
570         return LB_STATUS_ERROR_NOT_EXIST;
571 }
572
573 static inline int clear_from_pending_list(struct item *item)
574 {
575         Eina_List *l;
576         struct item *tmp;
577
578         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
579                 if (tmp != item)
580                         continue;
581
582                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
583                 if (!s_info.pending_list)
584                         deactivate_pending_consumer();
585                 return LB_STATUS_SUCCESS;
586         }
587
588         return LB_STATUS_ERROR_NOT_EXIST;
589 }
590
591 static Eina_Bool update_timeout_cb(void *data)
592 {
593         struct item *item;
594
595         item = data;
596
597         ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
598
599         if (s_info.update != item)
600                 ErrPrint("Updating item is not matched\n");
601
602         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
603         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
604         s_info.update = NULL;
605
606         exit(ETIME);
607         return ECORE_CALLBACK_CANCEL;
608 }
609
610 /*!
611  * \note
612  * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
613  * So every caller, should manage the deleted item correctly.
614  */
615 static Eina_Bool updator_cb(void *data)
616 {
617         struct item *item;
618         int ret;
619
620         item = data;
621
622         if (item->monitor) {/*!< If this item is already in update process */
623                 return ECORE_CALLBACK_RENEW;
624         }
625
626         if (!IS_LB_SHOWN(item)) {
627                 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
628                 (void)append_pending_list(item);
629                 return ECORE_CALLBACK_RENEW;
630         }
631
632         if (item->is_paused) {
633                 item->updated_in_pause++;
634                 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
635                 return ECORE_CALLBACK_RENEW;
636         }
637
638         item->updated_in_pause = 0;
639
640         ret = so_is_updated(item->inst);
641         if (ret <= 0) {
642                 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
643                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
644                         lb_destroy(item->inst->item->pkgname, item->inst->id);
645                         /*!
646                          * \CRITICAL
647                          * Every caller of this, must not access the item from now.
648                          */
649                         return ECORE_CALLBACK_CANCEL;
650                 }
651
652                 reset_lb_updated_flag(item);
653                 return ECORE_CALLBACK_RENEW;
654         }
655
656         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
657                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
658                 (void)append_pending_list(item);
659                 return ECORE_CALLBACK_RENEW;
660         }
661
662         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
663         if (!item->monitor) {
664                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
665                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
666                 return ECORE_CALLBACK_RENEW;
667         }
668
669         ret = so_update(item->inst);
670         if (ret < 0) {
671                 ecore_timer_del(item->monitor);
672                 item->monitor = NULL;
673                 reset_lb_updated_flag(item);
674                 return ECORE_CALLBACK_RENEW;
675         }
676
677         /*!
678          * \note
679          * Counter of the event monitor is only used for asynchronous content updating,
680          * So reset it to 1 from here because the async updating is started now,
681          * even if it is accumulated by other event function before this.
682          */
683         item->monitor_cnt = 1;
684
685         /*!
686          * \note
687          * While waiting the Callback function call,
688          * Add this for finding the crash
689          */
690         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
691
692         if (ret & NEED_TO_SCHEDULE)
693                 (void)append_pending_list(item);
694
695         if (ret & OUTPUT_UPDATED) {
696                 /*!
697                  * \NOTE 
698                  * In this case, there is potential issue
699                  * 1. User added update CALLBACK -> Inotify event (Only once)
700                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
701                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
702                  *    > Okay. What we want is this.
703                  */
704                 update_monitor_cnt(item);
705         }
706
707         /*
708          * \NOTE
709          * This should be updated after "update_monitor_cnt" function call,
710          * because the update_monitor_cnt function will see the s_info.update variable,
711          */
712         s_info.update = item;
713
714         return ECORE_CALLBACK_RENEW;
715 }
716
717 static inline void update_monitor_del(const char *id, struct item *item)
718 {
719         char *tmp;
720         int len;
721
722         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
723
724         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
725         tmp = malloc(len);
726         if (!tmp) {
727                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
728                 return;
729         }
730
731         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
732         update_monitor_del_update_cb(tmp, desc_updated_cb);
733         free(tmp);
734 }
735
736 static inline int add_desc_update_monitor(const char *id, struct item *item)
737 {
738         char *filename;
739         int len;
740         int ret;
741
742         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
743         filename = malloc(len);
744         if (!filename) {
745                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
746                 return LB_STATUS_ERROR_MEMORY;
747         }
748
749         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
750         ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
751         free(filename);
752         return ret;
753 }
754
755 static inline int add_file_update_monitor(const char *id, struct item *item)
756 {
757         return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
758 }
759
760 static inline int update_monitor_add(const char *id, struct item *item)
761 {
762         /*!
763          * \NOTE
764          * item->inst is not available yet.
765          */
766         add_file_update_monitor(id, item);
767         add_desc_update_monitor(id, item);
768         return LB_STATUS_SUCCESS;
769 }
770
771 HAPI int lb_init(void)
772 {
773         return LB_STATUS_SUCCESS;
774 }
775
776 HAPI int lb_fini(void)
777 {
778         Eina_List *l;
779         Eina_List *n;
780         struct item *item;
781
782         deactivate_pending_consumer();
783         deactivate_pd_open_pending_consumer();
784
785         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
786         EINA_LIST_FREE(s_info.pending_list, item);
787
788         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
789                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
790                 lb_destroy(item->inst->item->pkgname, item->inst->id);
791         }
792
793         return LB_STATUS_SUCCESS;
794 }
795
796 /*!
797  * \note
798  * Exported API for each liveboxes.
799  */
800 const char *livebox_find_pkgname(const char *filename)
801 {
802         Eina_List *l;
803         struct item *item;
804
805         EINA_LIST_FOREACH(s_info.item_list, l, item) {
806                 if (!strcmp(item->inst->id, filename))
807                         return item->inst->item->pkgname;
808         }
809
810         return NULL;
811 }
812
813 int livebox_request_update_by_id(const char *filename)
814 {
815         Eina_List *l;
816         struct item *item;
817
818         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
819                 ErrPrint("Current operation: %d\n", so_current_op());
820                 return LB_STATUS_ERROR_INVALID;
821         }
822
823         EINA_LIST_FOREACH(s_info.item_list, l, item) {
824                 if (!strcmp(item->inst->id, filename)) {
825                         return append_pending_list(item);
826                 }
827         }
828
829         return LB_STATUS_ERROR_NOT_EXIST;
830 }
831
832 int livebox_trigger_update_monitor(const char *filename, int is_pd)
833 {
834         char *fname;
835         int ret;
836
837         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
838                 ErrPrint("Current operation: %d\n", so_current_op());
839                 return LB_STATUS_ERROR_INVALID;
840         }
841
842         if (is_pd) {
843                 int len;
844                 len = strlen(filename) + strlen(".desc");
845
846                 fname = malloc(len + 1);
847                 if (!fname) {
848                         ErrPrint("Heap: %s\n", strerror(errno));
849                         return LB_STATUS_ERROR_MEMORY;
850                 }
851
852                 snprintf(fname, len, "%s.desc", filename);
853         } else {
854                 fname = strdup(filename);
855                 if (!fname) {
856                         ErrPrint("Heap: %s\n", strerror(errno));
857                         return LB_STATUS_ERROR_MEMORY;
858                 }
859         }
860
861         if (access(fname, R_OK | W_OK) != 0) {
862                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
863                 ret = LB_STATUS_ERROR_IO;
864         } else {
865                 ret = update_monitor_trigger_update_cb(fname, 0);
866         }
867
868         free(fname);
869         return ret;
870 }
871
872 HAPI int lb_open_pd(const char *pkgname)
873 {
874         Eina_List *l;
875         char *tmp;
876
877         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
878                 if (!strcmp(pkgname, tmp))
879                         return 0;
880         }
881
882         tmp = strdup(pkgname);
883         if (!tmp) {
884                 ErrPrint("Heap: %s\n", strerror(errno));
885                 return LB_STATUS_ERROR_MEMORY;
886         }
887
888         if (!s_info.pd_list)
889                 pending_timer_freeze();
890
891         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
892
893         /*!
894          * Find all instances from the pending list.
895          * Move them to pd_open_pending_timer
896          */
897         migrate_to_pd_open_pending_list(pkgname);
898         return LB_STATUS_SUCCESS;
899 }
900
901 HAPI int lb_close_pd(const char *pkgname)
902 {
903         Eina_List *l;
904         Eina_List *n;
905         char *tmp;
906
907         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
908                 if (strcmp(tmp, pkgname))
909                         continue;
910
911                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
912                 free(tmp);
913
914                 if (!s_info.pd_list)
915                         pending_timer_thaw();
916
917                 /*!
918                  * Move all items in pd_open_pending_list
919                  * to pending_list.
920                  */
921                 migrate_to_pending_list(pkgname);
922                 return LB_STATUS_SUCCESS;
923         }
924
925         return LB_STATUS_ERROR_NOT_EXIST;
926 }
927
928 HAPI int lb_create(const char *pkgname, const char *id, const char *content_info, int timeout, int has_livebox_script, double period, const char *cluster, const char *category, int *w, int *h, double *priority, int skip_need_to_create, const char *abi, char **out_content, char **out_title)
929 {
930         struct instance *inst;
931         struct item *item;
932         int ret;
933         int create_ret;
934         int need_to_create;
935
936         need_to_create = 0;
937         *out_content = NULL;
938         *out_title = NULL;
939
940         inst = so_find_instance(pkgname, id);
941         if (inst) {
942                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
943                 return LB_STATUS_SUCCESS;
944         }
945
946         if (!skip_need_to_create) {
947                 ret = so_create_needed(pkgname, cluster, category, abi);
948                 if (ret != NEED_TO_CREATE)
949                         return LB_STATUS_ERROR_PERMISSION;
950
951                 need_to_create = 1;
952         }
953
954         item = calloc(1, sizeof(*item));
955         if (!item) {
956                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
957                 return LB_STATUS_ERROR_MEMORY;
958         }
959
960         ret = update_monitor_add(id, item);
961         if (ret < 0) {
962                 free(item);
963                 return ret;
964         }
965
966         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
967         if (create_ret < 0) {
968                 update_monitor_del(id,  item);
969                 free(item);
970
971                 *w = 0;
972                 *h = 0;
973                 *priority = 0.0f;
974                 return create_ret;
975         }
976
977         item->inst = inst;
978
979         if (period > 0.0f && !s_info.secured) {
980                 item->timer = util_timer_add(period, updator_cb, item);
981                 if (!item->timer) {
982                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
983                         update_monitor_del(id, item);
984                         (void)so_destroy(inst);
985                         free(item);
986                         return LB_STATUS_ERROR_FAULT;
987                 }
988
989                 if (s_info.paused)
990                         timer_freeze(item);
991         } else {
992                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
993                 item->timer = NULL;
994         }
995
996         s_info.item_list = eina_list_append(s_info.item_list, item);
997
998         if (create_ret & NEED_TO_SCHEDULE) {
999                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1000                 (void)append_pending_list(item);
1001         }
1002
1003         if (create_ret & OUTPUT_UPDATED) {
1004                 update_monitor_cnt(item);
1005                 /*!
1006                  * \note
1007                  * To send a output info, get the info forcely.
1008                  * but the output file monitor will do this again
1009                  *
1010                  * This function will set the tmp_content and tmp_title
1011                  * even if it has no updates on the content, title,
1012                  * it will set them to NULL.
1013                  */
1014                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
1015                         if (*out_content) {
1016                                 char *tmp;
1017
1018                                 tmp = strdup(*out_content);
1019                                 if (!tmp)
1020                                         ErrPrint("Memory: %s\n", strerror(errno));
1021
1022                                 *out_content = tmp;
1023                         }
1024
1025                         if (*out_title) {
1026                                 char *tmp;
1027
1028                                 tmp = strdup(*out_title);
1029                                 if (!tmp)
1030                                         ErrPrint("Memory: %s\n", strerror(errno));
1031
1032                                 *out_title = tmp;
1033                         }
1034                 }
1035         }
1036
1037         *w = inst->w;
1038         *h = inst->h;
1039         *priority = inst->priority;
1040         return need_to_create;
1041 }
1042
1043 HAPI int lb_destroy(const char *pkgname, const char *id)
1044 {
1045         Eina_List *l;
1046         struct instance *inst;
1047         struct item *item;
1048
1049         inst = so_find_instance(pkgname, id);
1050         if (!inst) {
1051                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1052                 return LB_STATUS_ERROR_INVALID;
1053         }
1054
1055         l = find_item(inst);
1056         if (!l) {
1057                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1058                 return LB_STATUS_ERROR_NOT_EXIST;
1059         }
1060
1061         item = eina_list_data_get(l);
1062         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1063
1064         if (s_info.update == item)
1065                 s_info.update = NULL;
1066
1067         if (item->timer) {
1068                 clear_from_pd_open_pending_list(item);
1069                 clear_from_pending_list(item);
1070                 ecore_timer_del(item->timer);
1071                 item->timer = NULL;
1072
1073                 if (item->monitor)
1074                         item->deleteme = 1;
1075                 else
1076                         update_monitor_del(id, item);
1077         }
1078
1079         if (!item->monitor) {
1080                 free(item);
1081                 (void)so_destroy(inst);
1082         }
1083
1084         return LB_STATUS_SUCCESS;
1085 }
1086
1087 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1088 {
1089         Eina_List *l;
1090         struct instance *inst;
1091         struct item *item;
1092         int ret;
1093
1094         inst = so_find_instance(pkgname, id);
1095         if (!inst) {
1096                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1097                 return LB_STATUS_ERROR_INVALID;
1098         }
1099
1100         l = find_item(inst);
1101         if (!l) {
1102                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1103                 return LB_STATUS_ERROR_NOT_EXIST;
1104         }
1105
1106         item = eina_list_data_get(l);
1107
1108         ret = so_resize(inst, w, h);
1109         if (ret < 0)
1110                 return ret;
1111
1112         if (ret & NEED_TO_SCHEDULE) {
1113                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1114                 (void)append_pending_list(item);
1115         }
1116
1117         if (ret & OUTPUT_UPDATED)
1118                 update_monitor_cnt(item);
1119
1120         return LB_STATUS_SUCCESS;
1121 }
1122
1123 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1124 {
1125         struct instance *inst;
1126         char *ret;
1127
1128         inst = so_find_instance(pkgname, id);
1129         if (!inst) {
1130                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1131                 return NULL;
1132         }
1133
1134         ret = so_pinup(inst, pinup);
1135         return ret;
1136 }
1137
1138 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1139 {
1140         Eina_List *l;
1141         struct instance *inst;
1142         struct item *item;
1143
1144         inst = so_find_instance(pkgname, id);
1145         if (!inst) {
1146                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1147                 return LB_STATUS_ERROR_INVALID;
1148         }
1149
1150         l = find_item(inst);
1151         if (!l) {
1152                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1153                 return LB_STATUS_ERROR_NOT_EXIST;
1154         }
1155
1156         item = eina_list_data_get(l);
1157
1158         if (period <= 0.0f) {
1159                 if (item->timer) {
1160                         ecore_timer_del(item->timer);
1161                         item->timer = NULL;
1162                 }
1163         } else {
1164                 if (item->timer) {
1165                         util_timer_interval_set(item->timer, period);
1166                 } else if (!s_info.secured) {
1167                         item->timer = util_timer_add(period, updator_cb, item);
1168                         if (!item->timer) {
1169                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1170                                 return LB_STATUS_ERROR_FAULT;
1171                         }
1172
1173                         if (s_info.paused)
1174                                 timer_freeze(item);
1175                 }
1176         }
1177
1178         return LB_STATUS_SUCCESS;
1179 }
1180
1181 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1182 {
1183         Eina_List *l;
1184         struct instance *inst;
1185         struct item *item;
1186         int ret;
1187
1188         inst = so_find_instance(pkgname, id);
1189         if (!inst) {
1190                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1191                 return LB_STATUS_ERROR_INVALID;
1192         }
1193
1194         l = find_item(inst);
1195         if (!l) {
1196                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1197                 return LB_STATUS_ERROR_NOT_EXIST;
1198         }
1199
1200         item = eina_list_data_get(l);
1201
1202         ret = so_clicked(inst, event, timestamp, x, y);
1203         if (ret < 0)
1204                 return ret;
1205
1206         if (ret & NEED_TO_SCHEDULE) {
1207                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1208                 (void)append_pending_list(item);
1209         }
1210
1211         if (ret & OUTPUT_UPDATED)
1212                 update_monitor_cnt(item);
1213
1214         return LB_STATUS_SUCCESS;
1215 }
1216
1217 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1218 {
1219         Eina_List *l;
1220         struct instance *inst;
1221         struct item *item;
1222         int ret;
1223
1224         inst = so_find_instance(pkgname, id);
1225         if (!inst) {
1226                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1227                 return LB_STATUS_ERROR_INVALID;
1228         }
1229
1230         l = find_item(inst);
1231         if (!l) {
1232                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1233                 return LB_STATUS_ERROR_NOT_EXIST;
1234         }
1235
1236         item = eina_list_data_get(l);
1237
1238         if (emission && source && !strcmp(source, id)) {
1239                 if (item->inst->item->has_livebox_script) {
1240                         if (!strcmp(emission, "lb,show")) {
1241                                 item->is_lb_show = 1;
1242
1243                                 if (item->is_lb_updated && !is_pended_item(item))
1244                                         reset_lb_updated_flag(item);
1245
1246                                 source = util_uri_to_path(source);
1247                         } else if (!strcmp(emission, "lb,hide")) {
1248                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1249                                 item->is_lb_show = 0;
1250
1251                                 source = util_uri_to_path(source);
1252                         }
1253                 }
1254
1255                 if (!strcmp(emission, "pd,show")) {
1256                         item->is_pd_show = 1;
1257                         source = util_uri_to_path(source);
1258                 } else if (!strcmp(emission, "pd,hide")) {
1259                         item->is_pd_show = 0;
1260                         source = util_uri_to_path(source);
1261                 }
1262         }
1263
1264         ret = so_script_event(inst, emission, source, event_info);
1265         if (ret < 0)
1266                 return ret;
1267
1268         if (ret & NEED_TO_SCHEDULE) {
1269                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1270                 (void)append_pending_list(item);
1271         }
1272
1273         if (ret & OUTPUT_UPDATED)
1274                 update_monitor_cnt(item);
1275
1276         return LB_STATUS_SUCCESS;
1277 }
1278
1279 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1280 {
1281         Eina_List *l;
1282         struct instance *inst;
1283         struct item *item;
1284
1285         inst = so_find_instance(pkgname, id);
1286         if (!inst) {
1287                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1288                 return LB_STATUS_ERROR_INVALID;
1289         }
1290
1291         l = find_item(inst);
1292         if (!l) {
1293                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1294                 return LB_STATUS_ERROR_NOT_EXIST;
1295         }
1296
1297         item = eina_list_data_get(l);
1298         if (!item) {
1299                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1300                 return LB_STATUS_ERROR_FAULT;
1301         }
1302         /*!
1303          * NOTE:
1304          * item is not used.
1305          * Maybe this is not neccessary for this operation
1306          */
1307         return so_is_pinned_up(inst);
1308 }
1309
1310 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1311 {
1312         Eina_List *l;
1313         struct instance *inst;
1314         struct item *item;
1315         int ret;
1316
1317         inst = so_find_instance(pkgname, id);
1318         if (!inst) {
1319                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1320                 return LB_STATUS_ERROR_INVALID;
1321         }
1322
1323         l = find_item(inst);
1324         if (!l) {
1325                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1326                 return LB_STATUS_ERROR_NOT_EXIST;
1327         }
1328
1329         item = eina_list_data_get(l);
1330
1331         ret = so_change_group(inst, cluster, category);
1332         if (ret < 0)
1333                 return ret;
1334
1335         if (ret & NEED_TO_SCHEDULE) {
1336                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1337                 (void)append_pending_list(item);
1338         }
1339
1340         if (ret & OUTPUT_UPDATED)
1341                 update_monitor_cnt(item);
1342
1343         return LB_STATUS_SUCCESS;
1344 }
1345
1346 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1347 {
1348         int ret;
1349
1350         ret = so_sys_event(inst, event);
1351         if (ret < 0)
1352                 return ret;
1353
1354         if (ret & NEED_TO_SCHEDULE)
1355                 (void)append_pending_list(item);
1356
1357         if (ret & OUTPUT_UPDATED)
1358                 update_monitor_cnt(item);
1359
1360         return LB_STATUS_SUCCESS;
1361 }
1362
1363 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1364 {
1365         Eina_List *l;
1366         struct instance *inst;
1367         struct item *item;
1368
1369         inst = so_find_instance(pkgname, id);
1370         if (!inst) {
1371                 ErrPrint("instance %s - %s is not created\n");
1372                 return LB_STATUS_ERROR_INVALID;
1373         }
1374
1375         l = find_item(inst);
1376         if (!l) {
1377                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1378                 return LB_STATUS_ERROR_NOT_EXIST;
1379         }
1380
1381         item = eina_list_data_get(l);
1382         return lb_sys_event(inst, item, event);
1383 }
1384
1385 HAPI int lb_update(const char *pkgname, const char *id)
1386 {
1387         Eina_List *l;
1388         struct instance *inst;
1389         struct item *item;
1390
1391         inst = so_find_instance(pkgname, id);
1392         if (!inst) {
1393                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1394                 return LB_STATUS_ERROR_INVALID;
1395         }
1396
1397         l = find_item(inst);
1398         if (!l) {
1399                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1400                 return LB_STATUS_ERROR_NOT_EXIST;
1401         }
1402
1403         item = eina_list_data_get(l);
1404         (void)append_pending_list(item);
1405         return LB_STATUS_SUCCESS;
1406 }
1407
1408 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1409 {
1410         Eina_List *l;
1411         Eina_List *n;
1412         struct item *item;
1413
1414         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1415         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1416                 if (item->deleteme)
1417                         continue;
1418
1419                 if (cluster && strcasecmp(item->inst->cluster, cluster))
1420                         continue;
1421
1422                 if (category && strcasecmp(item->inst->category, category))
1423                         continue;
1424
1425                 if (pkgname && strlen(pkgname)) {
1426                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1427                                 (void)append_pending_list(item);
1428                         }
1429                 } else {
1430                         (void)append_pending_list(item);
1431                 }
1432         }
1433
1434         return LB_STATUS_SUCCESS;
1435 }
1436
1437 HAPI int lb_delete_all_deleteme(void)
1438 {
1439         Eina_List *l;
1440         Eina_List *n;
1441         struct item *item;
1442         int cnt = 0;
1443
1444         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1445                 if (!item->deleteme)
1446                         continue;
1447
1448                 update_monitor_del(item->inst->id, item);
1449                 (void)so_destroy(item->inst);
1450                 free(item);
1451                 cnt++;
1452         }
1453
1454         DbgPrint("Delete all deleteme: %d\n", cnt);
1455         return LB_STATUS_SUCCESS;
1456 }
1457
1458 HAPI int lb_system_event_all(int event)
1459 {
1460         Eina_List *l;
1461         Eina_List *n;
1462         struct item *item;
1463
1464         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1465                 if (item->deleteme)
1466                         continue;
1467
1468                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1469                 lb_sys_event(item->inst, item, event);
1470         }
1471
1472         return LB_STATUS_SUCCESS;
1473 }
1474
1475 HAPI void lb_pause_all(void)
1476 {
1477         Eina_List *l;
1478         struct item *item;
1479
1480         s_info.paused = 1;
1481
1482         pending_timer_freeze();
1483
1484         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1485                 if (item->deleteme) {
1486                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1487                         continue;
1488                 }
1489
1490                 if (item->is_paused)
1491                         continue;
1492
1493                 timer_freeze(item);
1494
1495                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1496         }
1497 }
1498
1499 HAPI void lb_resume_all(void)
1500 {
1501         Eina_List *l;
1502         Eina_List *n;
1503         struct item *item;
1504
1505         s_info.paused = 0;
1506
1507         pending_timer_thaw();
1508
1509         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1510                 if (item->deleteme) {
1511                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1512                         continue;
1513                 }
1514
1515                 if (item->is_paused)
1516                         continue;
1517
1518                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1519
1520                 if (item->updated_in_pause) {
1521                         (void)append_pending_list(item);
1522                         item->updated_in_pause = 0;
1523                 }
1524
1525                 /*!
1526                  * \note
1527                  * After send the resume callback, call this function.
1528                  * Because the timer_thaw can call the update function.
1529                  * Before resumed event is notified to the livebox,
1530                  * Do not call update function
1531                  */
1532                 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
1533                         /* item is deleted */
1534                 }
1535         }
1536 }
1537
1538 HAPI int lb_pause(const char *pkgname, const char *id)
1539 {
1540         struct instance *inst;
1541         Eina_List *l;
1542         struct item *item;
1543
1544         inst = so_find_instance(pkgname, id);
1545         if (!inst)
1546                 return LB_STATUS_ERROR_INVALID;
1547
1548         l = find_item(inst);
1549         if (!l) {
1550                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1551                 return LB_STATUS_ERROR_NOT_EXIST;
1552         }
1553
1554         item = eina_list_data_get(l);
1555         if (!item)
1556                 return LB_STATUS_ERROR_FAULT;
1557
1558         if (item->deleteme) {
1559                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1560                 return LB_STATUS_ERROR_BUSY;
1561         }
1562
1563         item->is_paused = 1;
1564
1565         if (s_info.paused)
1566                 return LB_STATUS_SUCCESS;
1567
1568         timer_freeze(item);
1569
1570         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1571
1572         return LB_STATUS_SUCCESS;
1573 }
1574
1575 HAPI int lb_resume(const char *pkgname, const char *id)
1576 {
1577         struct instance *inst;
1578         Eina_List *l;
1579         struct item *item;
1580         int ret;
1581
1582         inst = so_find_instance(pkgname, id);
1583         if (!inst)
1584                 return LB_STATUS_ERROR_INVALID;
1585
1586         l = find_item(inst);
1587         if (!l) {
1588                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1589                 return LB_STATUS_ERROR_NOT_EXIST;
1590         }
1591
1592         item = eina_list_data_get(l);
1593         if (!item)
1594                 return LB_STATUS_ERROR_FAULT;
1595
1596         if (item->deleteme) {
1597                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1598                 return LB_STATUS_ERROR_BUSY;
1599         }
1600
1601         item->is_paused = 0;
1602
1603         if (s_info.paused)
1604                 return LB_STATUS_SUCCESS;
1605
1606         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1607
1608         ret = timer_thaw(item);
1609         if (ret == UPDATE_ITEM_DELETED) {
1610                 /*!
1611                  * \note
1612                  * ITEM is deleted
1613                  */
1614                 return LB_STATUS_SUCCESS;
1615         } else if (ret == UPDATE_INVOKED) {
1616                 /*!
1617                  * \note
1618                  * if the update is successfully done, the updated_in_pause will be reset'd.
1619                  * or append it to the pending list
1620                  */
1621         }
1622
1623         if (item->updated_in_pause) {
1624                 (void)append_pending_list(item);
1625                 item->updated_in_pause = 0;
1626         }
1627
1628         return LB_STATUS_SUCCESS;
1629 }
1630
1631 HAPI void lb_turn_secured_on(void)
1632 {
1633         s_info.secured = 1;
1634 }
1635
1636 HAPI int lb_is_all_paused(void)
1637 {
1638         return s_info.paused;
1639 }
1640
1641 /* End of a file */