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