Merge "Use the ECORE_ERROR_ABORT env." into tizen_2.1
[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         if (!item->timer)
332                 return;
333
334         ecore_timer_thaw(item->timer);
335         period = ecore_timer_interval_get(item->timer);
336         pending = ecore_timer_pending_get(item->timer);
337         delay = util_time_delay_for_compensation(period) - pending;
338         ecore_timer_delay(item->timer, delay);
339         DbgPrint("Compensated: %lf, Instance %s resume timer\n", delay, item->inst->item->pkgname);
340
341         if (item->sleep_at == 0.0f)
342                 return;
343
344         sleep_time = util_timestamp() - item->sleep_at;
345         if (sleep_time > pending) {
346                 DbgPrint("Update time elapsed\n");
347                 (void)updator_cb(item);
348         }
349
350         item->sleep_at = 0.0f;
351 }
352
353 static inline void timer_freeze(struct item *item)
354 {
355         struct timeval tv;
356
357         if (!item->timer)
358                 return;
359
360         ecore_timer_freeze(item->timer);
361
362         if (ecore_timer_interval_get(item->timer) <= 1.0f)
363                 return;
364
365         if (gettimeofday(&tv, NULL) < 0) {
366                 ErrPrint("gettimeofday: %s\n", strerror(errno));
367                 tv.tv_sec = 0;
368                 tv.tv_usec = 0;
369         }
370
371         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
372         DbgPrint("Instance %s freeze timer\n", item->inst->item->pkgname);
373 }
374
375 static inline void update_monitor_cnt(struct item *item)
376 {
377         double now;
378         double interval;
379
380         now = util_timestamp();
381         interval = now - item->update_interval;
382
383         /*!
384          * \note
385          * If the content update is processed in too short time,
386          * don't increase the monitor counter, instead of it
387          * set the heavy updating flag.
388          * And handling this heavy updating from the
389          * file update callback.
390          */
391         if (interval >= MINIMUM_UPDATE_INTERVAL)
392                 item->monitor_cnt++;
393         else
394                 item->heavy_updating = 1;
395
396         item->update_interval = now;
397 }
398
399 static inline Eina_List *find_item(struct instance *inst)
400 {
401         Eina_List *l;
402         struct item *item;
403         
404         EINA_LIST_FOREACH(s_info.item_list, l, item) {
405                 if (item->inst == inst)
406                         return l;
407         }
408
409         return NULL;
410 }
411
412 static inline int output_handler(struct item *item)
413 {
414         int invalid = 0;
415
416         item->monitor_cnt--;
417         if (item->monitor_cnt < 0 || item->heavy_updating) {
418                 if (!item->heavy_updating) {
419                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
420                         invalid = 1;
421                 } else {
422                         item->heavy_updating = 0;       /* Reset flag */
423                 }
424
425                 item->monitor_cnt = 0;
426         }
427
428         if (item->monitor_cnt == 0) {
429                 if (!invalid)
430                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
431
432                 if (item->monitor) {
433                         ecore_timer_del(item->monitor);
434                         item->monitor = NULL;
435                 }
436
437                 if (s_info.update == item)
438                         s_info.update = NULL;
439
440                 if (item->deleteme) {
441                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
442                         (void)so_destroy(item->inst);
443                         free(item);
444                         return EXIT_FAILURE;
445                 }
446         }
447
448         return EXIT_SUCCESS;
449 }
450
451 static int desc_updated_cb(const char *filename, void *data, int over)
452 {
453         struct item *item;
454
455         if (over)
456                 WarnPrint("Event Q overflow\n");
457
458         item = data;
459
460         DbgPrint("DESC %s is updated\n", filename);
461         if (item->is_pd_show) {
462                 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
463         } else {
464                 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
465         }
466         return EXIT_SUCCESS;
467 }
468
469 static int file_updated_cb(const char *filename, void *data, int over)
470 {
471         struct item *item;
472         int w;
473         int h;
474         double priority;
475         char *content = NULL;
476         char *title = NULL;
477         int ret;
478
479         if (over)
480                 WarnPrint("Event Q overflow\n");
481
482         item = data;
483
484         ret = util_get_filesize(filename);
485         if (ret <= 0) {
486                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
487                 return EXIT_SUCCESS; /*!< To keep the callback */
488         }
489
490         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
491         if (ret < 0) {
492                 ErrPrint("livebox_get_info returns %d\n", ret);
493                 return EXIT_SUCCESS; /*!< To keep the callback */
494         }
495
496         if (!item->inst->item->has_livebox_script || (item->inst->item->has_livebox_script && item->is_lb_show)) {
497                 provider_send_updated(item->inst->item->pkgname, item->inst->id,
498                                         item->inst->w, item->inst->h, item->inst->priority, content, title);
499         } else {
500                 DbgPrint("Livebox script is not ready yet\n");
501                 item->is_lb_updated++;
502         }
503
504         return output_handler(item);
505 }
506
507 static inline int clear_from_pd_open_pending_list(struct item *item)
508 {
509         Eina_List *l;
510         struct item *tmp;
511
512         EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
513                 if (tmp != item)
514                         continue;
515
516                 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
517                 if (!s_info.pd_open_pending_list)
518                         deactivate_pd_open_pending_consumer();
519                 return LB_STATUS_SUCCESS;
520         }
521
522         return LB_STATUS_ERROR_NOT_EXIST;
523 }
524
525 static inline int clear_from_pending_list(struct item *item)
526 {
527         Eina_List *l;
528         struct item *tmp;
529
530         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
531                 if (tmp != item)
532                         continue;
533
534                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
535                 if (!s_info.pending_list)
536                         deactivate_pending_consumer();
537                 return LB_STATUS_SUCCESS;
538         }
539
540         return LB_STATUS_ERROR_NOT_EXIST;
541 }
542
543 static Eina_Bool update_timeout_cb(void *data)
544 {
545         struct item *item;
546
547         item = data;
548
549         DbgPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
550
551         if (s_info.update != item)
552                 ErrPrint("Updating item is not matched\n");
553
554         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
555         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
556         s_info.update = NULL;
557
558         exit(ETIME);
559         return ECORE_CALLBACK_CANCEL;
560 }
561
562 static Eina_Bool updator_cb(void *data)
563 {
564         struct item *item;
565         int ret;
566
567         item = data;
568
569         if (item->monitor) {/*!< If this item is already in update process */
570                 return ECORE_CALLBACK_RENEW;
571         }
572
573         ret = so_is_updated(item->inst);
574         if (ret <= 0) {
575                 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
576                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
577                         lb_destroy(item->inst->item->pkgname, item->inst->id);
578
579                         ecore_timer_del(item->timer);
580                         item->timer = NULL;
581                         return ECORE_CALLBACK_CANCEL;
582                 }
583
584                 return ECORE_CALLBACK_RENEW;
585         }
586
587         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
588                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
589                 (void)append_pending_list(item);
590                 return ECORE_CALLBACK_RENEW;
591         }
592
593         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
594         if (!item->monitor) {
595                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
596                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
597                 return ECORE_CALLBACK_RENEW;
598         }
599
600         /*!
601          * \note
602          * Counter of the event monitor is only used for asynchronous content updating,
603          * So reset it to 1 from here because the async updating is started now,
604          * even if it is accumulated by other event function before this.
605          */
606         item->monitor_cnt = 1;
607
608         s_info.update = item;
609
610         ret = so_update(item->inst);
611         if (ret < 0) {
612                 item->monitor_cnt--;
613
614                 ecore_timer_del(item->monitor);
615                 item->monitor = NULL;
616                 s_info.update = NULL;
617                 return ECORE_CALLBACK_RENEW;
618         }
619
620         /*!
621          * \note
622          * While waiting the Callback function call,
623          * Add this for finding the crash
624          */
625         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
626
627         if (ret & NEED_TO_SCHEDULE) {
628                 (void)append_pending_list(item);
629         }
630
631         if (ret & OUTPUT_UPDATED)
632                 update_monitor_cnt(item);
633
634         return ECORE_CALLBACK_RENEW;
635 }
636
637 static inline void update_monitor_del(const char *id, struct item *item)
638 {
639         char *tmp;
640         int len;
641
642         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
643
644         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
645         tmp = malloc(len);
646         if (!tmp) {
647                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
648                 return;
649         }
650
651         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
652         update_monitor_del_update_cb(tmp, desc_updated_cb);
653         free(tmp);
654 }
655
656 static inline int add_desc_update_monitor(const char *id, struct item *item)
657 {
658         char *filename;
659         int len;
660
661         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
662         filename = malloc(len);
663         if (!filename) {
664                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
665                 return LB_STATUS_ERROR_MEMORY;
666         }
667
668         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
669         DbgPrint("Add DESC monitor: %s\n", filename);
670         return update_monitor_add_update_cb(filename, desc_updated_cb, item);
671 }
672
673 static inline int add_file_update_monitor(const char *id, struct item *item)
674 {
675         char *filename;
676
677         filename = strdup(util_uri_to_path(id));
678         if (!filename) {
679                 ErrPrint("Heap: %s (%s)\n", strerror(errno), id);
680                 return LB_STATUS_ERROR_MEMORY;
681         }
682
683         return update_monitor_add_update_cb(filename, file_updated_cb, item);
684 }
685
686 static inline int update_monitor_add(const char *id, struct item *item)
687 {
688         /*!
689          * \NOTE
690          * item->inst is not available yet.
691          */
692         add_file_update_monitor(id, item);
693         add_desc_update_monitor(id, item);
694         return LB_STATUS_SUCCESS;
695 }
696
697 HAPI int lb_init(void)
698 {
699         return LB_STATUS_SUCCESS;
700 }
701
702 HAPI int lb_fini(void)
703 {
704         Eina_List *l;
705         Eina_List *n;
706         struct item *item;
707
708         deactivate_pending_consumer();
709         deactivate_pd_open_pending_consumer();
710
711         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
712         EINA_LIST_FREE(s_info.pending_list, item);
713
714         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
715                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
716                 lb_destroy(item->inst->item->pkgname, item->inst->id);
717         }
718
719         return LB_STATUS_SUCCESS;
720 }
721
722 /*!
723  * \note
724  * Exported API for each liveboxes.
725  */
726 const char *livebox_find_pkgname(const char *filename)
727 {
728         Eina_List *l;
729         struct item *item;
730
731         EINA_LIST_FOREACH(s_info.item_list, l, item) {
732                 if (!strcmp(item->inst->id, filename))
733                         return item->inst->item->pkgname;
734         }
735
736         return NULL;
737 }
738
739 int livebox_request_update_by_id(const char *filename)
740 {
741         Eina_List *l;
742         struct item *item;
743
744         EINA_LIST_FOREACH(s_info.item_list, l, item) {
745                 if (!strcmp(item->inst->id, filename)) {
746                         return append_pending_list(item);
747                 }
748         }
749
750         return LB_STATUS_ERROR_NOT_EXIST;
751 }
752
753 HAPI int lb_open_pd(const char *pkgname)
754 {
755         Eina_List *l;
756         char *tmp;
757
758         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
759                 if (!strcmp(pkgname, tmp))
760                         return 0;
761         }
762
763         tmp = strdup(pkgname);
764         if (!tmp) {
765                 ErrPrint("Heap: %s\n", strerror(errno));
766                 return LB_STATUS_ERROR_MEMORY;
767         }
768
769         if (!s_info.pd_list)
770                 pending_timer_freeze();
771
772         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
773
774         /*!
775          * Find all instances from the pending list.
776          * Move them to pd_open_pending_timer
777          */
778         migrate_to_pd_open_pending_list(pkgname);
779         return LB_STATUS_SUCCESS;
780 }
781
782 HAPI int lb_close_pd(const char *pkgname)
783 {
784         Eina_List *l;
785         Eina_List *n;
786         char *tmp;
787
788         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
789                 if (strcmp(tmp, pkgname))
790                         continue;
791
792                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
793                 free(tmp);
794
795                 if (!s_info.pd_list)
796                         pending_timer_thaw();
797
798                 /*!
799                  * Move all items in pd_open_pending_list
800                  * to pending_list.
801                  */
802                 migrate_to_pending_list(pkgname);
803                 return LB_STATUS_SUCCESS;
804         }
805
806         return LB_STATUS_ERROR_NOT_EXIST;
807 }
808
809 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)
810 {
811         struct instance *inst;
812         struct item *item;
813         int ret;
814         int create_ret;
815         int need_to_create;
816
817         need_to_create = 0;
818         *out_content = NULL;
819         *out_title = NULL;
820
821         inst = so_find_instance(pkgname, id);
822         if (inst) {
823                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
824                 return LB_STATUS_SUCCESS;
825         }
826
827         if (!skip_need_to_create) {
828                 ret = so_create_needed(pkgname, cluster, category, abi);
829                 if (ret != NEED_TO_CREATE)
830                         return LB_STATUS_ERROR_PERMISSION;
831
832                 need_to_create = 1;
833         }
834
835         item = calloc(1, sizeof(*item));
836         if (!item) {
837                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
838                 return LB_STATUS_ERROR_MEMORY;
839         }
840
841         ret = update_monitor_add(id, item);
842         if (ret < 0) {
843                 free(item);
844                 return ret;
845         }
846
847         DbgPrint("Content: [%s]\n", content_info);
848         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
849         if (create_ret < 0) {
850                 update_monitor_del(id,  item);
851                 free(item);
852
853                 *w = 0;
854                 *h = 0;
855                 *priority = 0.0f;
856                 return create_ret;
857         }
858
859         item->inst = inst;
860
861         if (period > 0.0f && !s_info.secured) {
862                 item->timer = util_timer_add(period, updator_cb, item);
863                 if (!item->timer) {
864                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
865                         update_monitor_del(id, item);
866                         (void)so_destroy(inst);
867                         free(item);
868                         return LB_STATUS_ERROR_FAULT;
869                 }
870
871                 if (s_info.paused)
872                         timer_freeze(item);
873         } else {
874                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
875                 item->timer = NULL;
876         }
877
878         s_info.item_list = eina_list_append(s_info.item_list, item);
879
880         if (create_ret & NEED_TO_SCHEDULE) {
881                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
882                 (void)append_pending_list(item);
883         }
884
885         if (create_ret & OUTPUT_UPDATED) {
886                 update_monitor_cnt(item);
887                 /*!
888                  * \note
889                  * To send a output info, get the info forcely.
890                  * but the output file monitor will do this again
891                  *
892                  * This function will set the tmp_content and tmp_title
893                  * even if it has no updates on the content, title,
894                  * it will set them to NULL.
895                  */
896                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
897                         if (*out_content) {
898                                 char *tmp;
899
900                                 tmp = strdup(*out_content);
901                                 if (!tmp)
902                                         ErrPrint("Memory: %s\n", strerror(errno));
903
904                                 *out_content = tmp;
905                         }
906
907                         if (*out_title) {
908                                 char *tmp;
909
910                                 tmp = strdup(*out_title);
911                                 if (!tmp)
912                                         ErrPrint("Memory: %s\n", strerror(errno));
913
914                                 *out_title = tmp;
915                         }
916                 }
917         }
918
919         *w = inst->w;
920         *h = inst->h;
921         *priority = inst->priority;
922         return need_to_create;
923 }
924
925 HAPI int lb_destroy(const char *pkgname, const char *id)
926 {
927         Eina_List *l;
928         struct instance *inst;
929         struct item *item;
930
931         inst = so_find_instance(pkgname, id);
932         if (!inst) {
933                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
934                 return LB_STATUS_ERROR_INVALID;
935         }
936
937         l = find_item(inst);
938         if (!l) {
939                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
940                 return LB_STATUS_ERROR_NOT_EXIST;
941         }
942
943         item = eina_list_data_get(l);
944         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
945
946         if (s_info.update == item)
947                 s_info.update = NULL;
948
949         if (item->timer) {
950                 clear_from_pd_open_pending_list(item);
951                 clear_from_pending_list(item);
952                 ecore_timer_del(item->timer);
953                 item->timer = NULL;
954
955                 if (item->monitor)
956                         item->deleteme = 1;
957                 else
958                         update_monitor_del(id, item);
959         }
960
961         if (!item->monitor) {
962                 free(item);
963                 (void)so_destroy(inst);
964         }
965
966         return LB_STATUS_SUCCESS;
967 }
968
969 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
970 {
971         Eina_List *l;
972         struct instance *inst;
973         struct item *item;
974         int ret;
975
976         inst = so_find_instance(pkgname, id);
977         if (!inst) {
978                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
979                 return LB_STATUS_ERROR_INVALID;
980         }
981
982         l = find_item(inst);
983         if (!l) {
984                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
985                 return LB_STATUS_ERROR_NOT_EXIST;
986         }
987
988         item = eina_list_data_get(l);
989
990         ret = so_resize(inst, w, h);
991         if (ret < 0)
992                 return ret;
993
994         if (ret & NEED_TO_SCHEDULE) {
995                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
996                 (void)append_pending_list(item);
997         }
998
999         if (ret & OUTPUT_UPDATED)
1000                 update_monitor_cnt(item);
1001
1002         return LB_STATUS_SUCCESS;
1003 }
1004
1005 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1006 {
1007         struct instance *inst;
1008         char *ret;
1009
1010         inst = so_find_instance(pkgname, id);
1011         if (!inst) {
1012                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1013                 return NULL;
1014         }
1015
1016         ret = so_pinup(inst, pinup);
1017         return ret;
1018 }
1019
1020 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1021 {
1022         Eina_List *l;
1023         struct instance *inst;
1024         struct item *item;
1025
1026         inst = so_find_instance(pkgname, id);
1027         if (!inst) {
1028                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1029                 return LB_STATUS_ERROR_INVALID;
1030         }
1031
1032         l = find_item(inst);
1033         if (!l) {
1034                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1035                 return LB_STATUS_ERROR_NOT_EXIST;
1036         }
1037
1038         item = eina_list_data_get(l);
1039
1040         if (period <= 0.0f) {
1041                 if (item->timer) {
1042                         ecore_timer_del(item->timer);
1043                         item->timer = NULL;
1044                 }
1045         } else {
1046                 if (item->timer) {
1047                         util_timer_interval_set(item->timer, period);
1048                 } else if (!s_info.secured) {
1049                         item->timer = util_timer_add(period, updator_cb, item);
1050                         if (!item->timer) {
1051                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1052                                 return LB_STATUS_ERROR_FAULT;
1053                         }
1054
1055                         if (s_info.paused)
1056                                 timer_freeze(item);
1057                 }
1058         }
1059
1060         return LB_STATUS_SUCCESS;
1061 }
1062
1063 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1064 {
1065         Eina_List *l;
1066         struct instance *inst;
1067         struct item *item;
1068         int ret;
1069
1070         inst = so_find_instance(pkgname, id);
1071         if (!inst) {
1072                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1073                 return LB_STATUS_ERROR_INVALID;
1074         }
1075
1076         l = find_item(inst);
1077         if (!l) {
1078                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1079                 return LB_STATUS_ERROR_NOT_EXIST;
1080         }
1081
1082         item = eina_list_data_get(l);
1083
1084         ret = so_clicked(inst, event, timestamp, x, y);
1085         if (ret < 0)
1086                 return ret;
1087
1088         if (ret & NEED_TO_SCHEDULE) {
1089                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1090                 (void)append_pending_list(item);
1091         }
1092
1093         if (ret & OUTPUT_UPDATED)
1094                 update_monitor_cnt(item);
1095
1096         return LB_STATUS_SUCCESS;
1097 }
1098
1099 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1100 {
1101         Eina_List *l;
1102         struct instance *inst;
1103         struct item *item;
1104         int ret;
1105
1106         inst = so_find_instance(pkgname, id);
1107         if (!inst) {
1108                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1109                 return LB_STATUS_ERROR_INVALID;
1110         }
1111
1112         l = find_item(inst);
1113         if (!l) {
1114                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1115                 return LB_STATUS_ERROR_NOT_EXIST;
1116         }
1117
1118         item = eina_list_data_get(l);
1119
1120         DbgPrint("source(%s) emission(%s) %d\n", source, emission, item->inst->item->has_livebox_script);
1121         if (emission && source && !strcmp(source, util_uri_to_path(id))) {
1122                 if (item->inst->item->has_livebox_script) {
1123                         if (!strcmp(emission, "lb,show")) {
1124                                 DbgPrint("Livebox(%s) script is ready now\n", id);
1125                                 item->is_lb_show = 1;
1126
1127                                 DbgPrint("Updated %d times, (content: %s), (title: %s)\n", item->is_lb_updated, item->inst->content, item->inst->title);
1128                                 if (item->is_lb_updated) {
1129                                         provider_send_updated(item->inst->item->pkgname, item->inst->id,
1130                                                                 item->inst->w, item->inst->h, item->inst->priority, item->inst->content, item->inst->title);
1131                                         item->is_lb_updated = 0;
1132                                 }
1133                         } else if (!strcmp(emission, "lb,hide")) {
1134                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1135                                 item->is_lb_show = 0;
1136                         }
1137                 }
1138
1139                 if (!strcmp(emission, "pd,show")) {
1140                         item->is_pd_show = 1;
1141                 } else if (!strcmp(emission, "pd,hide")) {
1142                         item->is_pd_show = 0;
1143                 }
1144         }
1145
1146         ret = so_script_event(inst, emission, source, event_info);
1147         if (ret < 0)
1148                 return ret;
1149
1150         if (ret & NEED_TO_SCHEDULE) {
1151                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1152                 (void)append_pending_list(item);
1153         }
1154
1155         if (ret & OUTPUT_UPDATED)
1156                 update_monitor_cnt(item);
1157
1158         return LB_STATUS_SUCCESS;
1159 }
1160
1161 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1162 {
1163         Eina_List *l;
1164         struct instance *inst;
1165         struct item *item;
1166
1167         inst = so_find_instance(pkgname, id);
1168         if (!inst) {
1169                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1170                 return LB_STATUS_ERROR_INVALID;
1171         }
1172
1173         l = find_item(inst);
1174         if (!l) {
1175                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1176                 return LB_STATUS_ERROR_NOT_EXIST;
1177         }
1178
1179         item = eina_list_data_get(l);
1180         if (!item) {
1181                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1182                 return LB_STATUS_ERROR_FAULT;
1183         }
1184         /*!
1185          * NOTE:
1186          * item is not used.
1187          * Maybe this is not neccessary for this operation
1188          */
1189         return so_is_pinned_up(inst);
1190 }
1191
1192 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1193 {
1194         Eina_List *l;
1195         struct instance *inst;
1196         struct item *item;
1197         int ret;
1198
1199         inst = so_find_instance(pkgname, id);
1200         if (!inst) {
1201                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1202                 return LB_STATUS_ERROR_INVALID;
1203         }
1204
1205         l = find_item(inst);
1206         if (!l) {
1207                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1208                 return LB_STATUS_ERROR_NOT_EXIST;
1209         }
1210
1211         item = eina_list_data_get(l);
1212
1213         ret = so_change_group(inst, cluster, category);
1214         if (ret < 0)
1215                 return ret;
1216
1217         if (ret & NEED_TO_SCHEDULE) {
1218                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1219                 (void)append_pending_list(item);
1220         }
1221
1222         if (ret & OUTPUT_UPDATED)
1223                 update_monitor_cnt(item);
1224
1225         return LB_STATUS_SUCCESS;
1226 }
1227
1228 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1229 {
1230         int ret;
1231
1232         ret = so_sys_event(inst, event);
1233         if (ret < 0)
1234                 return ret;
1235
1236         if (ret & NEED_TO_SCHEDULE)
1237                 (void)append_pending_list(item);
1238
1239         if (ret & OUTPUT_UPDATED)
1240                 update_monitor_cnt(item);
1241
1242         return LB_STATUS_SUCCESS;
1243 }
1244
1245 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1246 {
1247         Eina_List *l;
1248         struct instance *inst;
1249         struct item *item;
1250
1251         inst = so_find_instance(pkgname, id);
1252         if (!inst) {
1253                 ErrPrint("instance %s - %s is not created\n");
1254                 return LB_STATUS_ERROR_INVALID;
1255         }
1256
1257         l = find_item(inst);
1258         if (!l) {
1259                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1260                 return LB_STATUS_ERROR_NOT_EXIST;
1261         }
1262
1263         item = eina_list_data_get(l);
1264         return lb_sys_event(inst, item, event);
1265 }
1266
1267 HAPI int lb_update(const char *pkgname, const char *id)
1268 {
1269         Eina_List *l;
1270         struct instance *inst;
1271         struct item *item;
1272
1273         inst = so_find_instance(pkgname, id);
1274         if (!inst) {
1275                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1276                 return LB_STATUS_ERROR_INVALID;
1277         }
1278
1279         l = find_item(inst);
1280         if (!l) {
1281                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1282                 return LB_STATUS_ERROR_NOT_EXIST;
1283         }
1284
1285         item = eina_list_data_get(l);
1286         (void)append_pending_list(item);
1287         return LB_STATUS_SUCCESS;
1288 }
1289
1290 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1291 {
1292         Eina_List *l;
1293         Eina_List *n;
1294         struct item *item;
1295
1296         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1297         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1298                 if (item->deleteme)
1299                         continue;
1300
1301                 if (cluster && strcasecmp(item->inst->cluster, cluster))
1302                         continue;
1303
1304                 if (category && strcasecmp(item->inst->category, category))
1305                         continue;
1306
1307                 if (pkgname && strlen(pkgname)) {
1308                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1309                                 (void)append_pending_list(item);
1310                         }
1311                 } else {
1312                         (void)append_pending_list(item);
1313                 }
1314         }
1315
1316         return LB_STATUS_SUCCESS;
1317 }
1318
1319 HAPI int lb_delete_all_deleteme(void)
1320 {
1321         Eina_List *l;
1322         Eina_List *n;
1323         struct item *item;
1324         int cnt = 0;
1325
1326         DbgPrint("Delete all deleteme\n");
1327         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1328                 if (!item->deleteme)
1329                         continue;
1330
1331                 s_info.item_list = eina_list_remove(s_info.item_list, item);
1332
1333                 update_monitor_del(item->inst->id, item);
1334                 (void)so_destroy(item->inst);
1335                 free(item);
1336                 cnt++;
1337         }
1338
1339         DbgPrint("Deleteme: %d\n", cnt);
1340         return LB_STATUS_SUCCESS;
1341 }
1342
1343 HAPI int lb_system_event_all(int event)
1344 {
1345         Eina_List *l;
1346         Eina_List *n;
1347         struct item *item;
1348
1349         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1350                 if (item->deleteme)
1351                         continue;
1352
1353                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1354                 lb_sys_event(item->inst, item, event);
1355         }
1356
1357         return LB_STATUS_SUCCESS;
1358 }
1359
1360 HAPI void lb_pause_all(void)
1361 {
1362         Eina_List *l;
1363         struct item *item;
1364
1365         s_info.paused = 1;
1366
1367         pending_timer_freeze();
1368
1369         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1370                 if (item->deleteme) {
1371                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1372                         continue;
1373                 }
1374
1375                 if (item->is_paused) {
1376                         DbgPrint("Instance %s is already paused\n", item->inst->id);
1377                         continue;
1378                 }
1379
1380                 timer_freeze(item);
1381
1382                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1383         }
1384 }
1385
1386 HAPI void lb_resume_all(void)
1387 {
1388         Eina_List *l;
1389         struct item *item;
1390
1391         s_info.paused = 0;
1392
1393         pending_timer_thaw();
1394
1395         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1396                 if (item->deleteme) {
1397                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1398                         continue;
1399                 }
1400
1401                 if (item->is_paused) {
1402                         DbgPrint("Instance %s is still paused\n", item->inst->id);
1403                         continue;
1404                 }
1405
1406                 timer_thaw(item);
1407
1408                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1409         }
1410 }
1411
1412 HAPI int lb_pause(const char *pkgname, const char *id)
1413 {
1414         struct instance *inst;
1415         Eina_List *l;
1416         struct item *item;
1417
1418         inst = so_find_instance(pkgname, id);
1419         if (!inst)
1420                 return LB_STATUS_ERROR_INVALID;
1421
1422         l = find_item(inst);
1423         if (!l) {
1424                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1425                 return LB_STATUS_ERROR_NOT_EXIST;
1426         }
1427
1428         item = eina_list_data_get(l);
1429         if (!item)
1430                 return LB_STATUS_ERROR_FAULT;
1431
1432         if (item->deleteme) {
1433                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1434                 return LB_STATUS_ERROR_BUSY;
1435         }
1436
1437         item->is_paused = 1;
1438
1439         if (s_info.paused) {
1440                 DbgPrint("Already paused: %s\n", item->inst->id);
1441                 return LB_STATUS_SUCCESS;
1442         }
1443
1444         timer_freeze(item);
1445
1446         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1447
1448         return LB_STATUS_SUCCESS;
1449 }
1450
1451 HAPI int lb_resume(const char *pkgname, const char *id)
1452 {
1453         struct instance *inst;
1454         Eina_List *l;
1455         struct item *item;
1456
1457         inst = so_find_instance(pkgname, id);
1458         if (!inst)
1459                 return LB_STATUS_ERROR_INVALID;
1460
1461         l = find_item(inst);
1462         if (!l) {
1463                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1464                 return LB_STATUS_ERROR_NOT_EXIST;
1465         }
1466
1467         item = eina_list_data_get(l);
1468         if (!item)
1469                 return LB_STATUS_ERROR_FAULT;
1470
1471         if (item->deleteme) {
1472                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1473                 return LB_STATUS_ERROR_BUSY;
1474         }
1475
1476         item->is_paused = 0;
1477
1478         if (s_info.paused) {
1479                 DbgPrint("Instance %s is still paused\n", item->inst->id);
1480                 return LB_STATUS_SUCCESS;
1481         }
1482
1483         timer_thaw(item);
1484
1485         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1486         return LB_STATUS_SUCCESS;
1487 }
1488
1489 HAPI void lb_turn_secured_on(void)
1490 {
1491         s_info.secured = 1;
1492 }
1493
1494 HAPI int lb_is_all_paused(void)
1495 {
1496         return s_info.paused;
1497 }
1498
1499 /* End of a file */