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