671f8ec5f4ffcf9dd7d744b98256e231e32f4a5b
[platform/core/appfw/data-provider-slave.git] / src / widget.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h> /* exit */
19 #include <errno.h>
20 #include <unistd.h> /* access */
21
22 #include <Ecore.h>
23 #include <Eina.h>
24
25 #include <dlog.h>
26 #include <widget_provider.h>
27 #include <widget_provider_buffer.h>
28 #include <widget/widget_internal.h>
29 #include <widget/widget.h>
30 #include <widget_errno.h>
31 #include <widget_service.h>
32 #include <widget_util.h>
33 #include <widget_service_internal.h>
34 #include <com-core_packet.h>
35
36 #include "critical_log.h"
37 #include "debug.h"
38 #include "so_handler.h"
39 #include "widget.h"
40 #include "update_monitor.h"
41 #include "fault.h"
42 #include "util.h"
43 #include "connection.h"
44 #include "conf.h"
45
46 #if defined(_ESTIMATE_PERF)
47 #define ESTIMATE_START(id)      DbgPrint("%s START\n", id);
48 #define ESTIMATE_END(id)        DbgPrint("%s END\n", id);
49 #else
50 #define ESTIMATE_START(id)
51 #define ESTIMATE_END(id)
52 #endif
53
54 #define IS_WIDGET_SHOWN(itm) (!(itm)->inst->item->has_widget_script || ((itm)->inst->item->has_widget_script && (itm)->is_widget_show))
55
56 int errno;
57
58 #define UPDATE_ITEM_DELETED     (-1)
59 #define UPDATE_INVOKED          (-2)
60 #define UPDATE_NOT_INVOKED      (0)
61
62 enum gbar_open_state {
63         GBAR_IS_OPENED_BUT_NOT_MINE = -1,
64         GBAR_IS_NOT_OPENED = 0,
65         GBAR_IS_OPENED = 1,
66 };
67
68 enum state {
69         STATE_UNKNOWN = 0,
70         STATE_RESUMED = 1,
71         STATE_PAUSED = 2
72 };
73
74 struct item {
75         Ecore_Timer *timer;
76         struct instance *inst;
77         int monitor_cnt;
78         Ecore_Timer *monitor;
79         int deleteme;
80         double update_interval;
81         int heavy_updating; /* Only for debugging message */
82         enum state state; /* 1 is paused, 0 is resumed */
83         double sleep_at;
84
85         unsigned int updated_in_pause;
86
87         int is_widget_show;
88         int is_gbar_show;
89         int is_widget_updated;
90         int unload_so;
91         Eina_List *direct_path_list;
92 };
93
94 static struct info {
95         Eina_List *item_list;
96         Eina_List *force_update_list;
97         Eina_List *update_list;
98         Eina_List *pending_list;
99         Eina_List *hidden_list;
100         Ecore_Timer *force_update_timer;
101         Ecore_Timer *pending_timer;
102         Eina_List *gbar_open_pending_list;
103         Ecore_Timer *gbar_open_pending_timer;
104         enum state state;
105         Eina_List *gbar_list;
106         int secured;
107         int pending_timer_freezed;
108         int force_timer_freezed;
109 } s_info  = {
110         .item_list = NULL,
111         .force_update_list = NULL,
112         .update_list = NULL,
113         .pending_list = NULL,
114         .hidden_list = NULL,
115         .force_update_timer = NULL,
116         .pending_timer = NULL,
117         .gbar_open_pending_list = NULL,
118         .gbar_open_pending_timer = NULL,
119         .state = STATE_UNKNOWN,
120         .gbar_list = NULL,
121         .secured = 0,
122         .pending_timer_freezed = 0,
123         .force_timer_freezed = 0,
124 };
125
126 static Eina_Bool updator_cb(void *data);
127 static inline void update_monitor_del(const char *id, struct item *item);
128 static int append_force_update_list(struct item *item);
129 static void reset_widget_updated_flag(struct item *item);
130 static int append_pending_list(struct item *item);
131
132 static void pending_timer_freeze(void)
133 {
134         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
135         if (!s_info.pending_timer) {
136                 return;
137         }
138
139         if (!s_info.pending_timer_freezed) {
140                 DbgPrint("Freeze the pending timer\n");
141                 ecore_timer_freeze(s_info.pending_timer);
142         }
143
144         s_info.pending_timer_freezed++;
145 }
146
147 static void pending_timer_thaw(void)
148 {
149         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
150         if (!s_info.pending_timer_freezed) {
151                 return;
152         }
153
154         if (!s_info.pending_timer) {
155                 s_info.pending_timer_freezed = 0;
156                 return;
157         }
158
159         s_info.pending_timer_freezed--;
160         if (!s_info.pending_timer_freezed) {
161                 DbgPrint("Thaw the pending timer\n");
162                 ecore_timer_thaw(s_info.pending_timer);
163         }
164 }
165
166 static void force_timer_freeze(void)
167 {
168         DbgPrint("Freeze force timer: %d\n", s_info.force_timer_freezed);
169         if (!s_info.force_update_timer) {
170                 return;
171         }
172
173         if (!s_info.force_timer_freezed) {
174                 DbgPrint("Force timer freezed\n");
175                 ecore_timer_freeze(s_info.force_update_timer);
176         }
177
178         s_info.force_timer_freezed++;
179 }
180
181 static void force_timer_thaw(void)
182 {
183         DbgPrint("Freezed force count: %d\n", s_info.force_timer_freezed);
184         if (!s_info.force_timer_freezed) {
185                 return;
186         }
187
188         if (!s_info.force_update_timer) {
189                 s_info.force_timer_freezed = 0;
190                 return;
191         }
192
193         s_info.force_timer_freezed--;
194         if (!s_info.force_timer_freezed) {
195                 DbgPrint("Thaw the force timer\n");
196                 ecore_timer_thaw(s_info.force_update_timer);
197         }
198 }
199
200 /*
201  * -1 : GBAR is opened, but not mine
202  *  0 : GBAR is not opened
203  *  1 : my GBAR is opened
204  */
205 static inline enum gbar_open_state gbar_is_opened(const char *pkgname)
206 {
207         int i;
208         Eina_List *l;
209         struct instance *inst;
210
211         i = 0;
212         EINA_LIST_FOREACH(s_info.gbar_list, l, inst) {
213                 if (pkgname && !strcmp(pkgname, inst->item->pkgname)) {
214                         return GBAR_IS_OPENED;
215                 }
216
217                 i++;
218         }
219
220         return i > 0 ? GBAR_IS_OPENED_BUT_NOT_MINE : GBAR_IS_NOT_OPENED;
221 }
222
223 static Eina_Bool gbar_open_pended_cmd_consumer_cb(void *data)
224 {
225         struct item *item;
226
227         item = eina_list_nth(s_info.gbar_open_pending_list, 0);
228         if (!item) {
229                 goto cleanout;
230         }
231
232         if (eina_list_data_find(s_info.update_list, item)) {
233                 return ECORE_CALLBACK_RENEW;
234         }
235
236         s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
237         /*!
238          * \note
239          * To prevent from checking the is_updated function
240          */
241         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
242                 /* Item is destroyed */
243         }
244
245         if (s_info.gbar_open_pending_list) {
246                 return ECORE_CALLBACK_RENEW;
247         }
248
249 cleanout:
250         s_info.gbar_open_pending_timer = NULL;
251         return ECORE_CALLBACK_CANCEL;
252 }
253
254 static Eina_Bool update_timeout_cb(void *data)
255 {
256         struct item *item;
257
258         item = data;
259
260         ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
261
262         if (!eina_list_data_find(s_info.update_list, item)) {
263                 ErrPrint("Updating item is not matched\n");
264         }
265
266         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
267         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
268         s_info.update_list = eina_list_remove(s_info.update_list, item);
269
270         exit(ETIME);
271         return ECORE_CALLBACK_CANCEL;
272 }
273
274 static inline void update_monitor_cnt(struct item *item)
275 {
276         double now;
277         double interval;
278
279         now = util_timestamp();
280         interval = now - item->update_interval;
281
282         /*!
283          * \note
284          * If the content update is processed in too short time,
285          * don't increase the monitor counter, instead of it
286          * set the heavy updating flag.
287          * And handling this heavy updating from the
288          * file update callback.
289          */
290         if (interval >= MINIMUM_UPDATE_INTERVAL) {
291                 if (eina_list_data_find(s_info.update_list, item)) {
292                         /*!
293                          * \note
294                          * If already in updating mode,
295                          * reset the monitor_cnt to 1,
296                          * all updated event will be merged into A inotify event
297                          */
298                         DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
299                         item->monitor_cnt = 1;
300                 } else {
301                         item->monitor_cnt++;
302                 }
303         } else {
304                 item->heavy_updating = 1;
305         }
306
307         item->update_interval = now;
308 }
309
310 static inline void do_force_update(struct item *item)
311 {
312         int ret;
313
314         if (item->monitor) { /*!< If this item is already in update process */
315                 return;
316         }
317
318         if (!IS_WIDGET_SHOWN(item)) {
319                 DbgPrint("%s is not shown yet. it will be added to normal pending list\n", item->inst->item->pkgname);
320                 (void)append_force_update_list(item);
321                 return;
322         }
323
324         if (item->state != STATE_RESUMED) {
325                 DbgPrint("Item is paused. but it will be updated forcely(%s)\n", item->inst->item->pkgname);
326         }
327
328         item->updated_in_pause = 0;
329
330         ret = so_is_updated(item->inst);
331         if (ret <= 0) {
332                 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
333                         widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
334                         widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
335                         /*!
336                          * \CRITICAL
337                          * Every caller of this, must not access the item from now.
338                          */
339                         return;
340                 }
341
342                 reset_widget_updated_flag(item);
343                 return;
344         }
345
346         /*!
347          * \note
348          * Check the update_list, if you want make serialized update
349          */
350         if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
351                 DbgPrint("%s is busy, migrate to normal pending list\n", item->inst->id);
352                 (void)append_pending_list(item);
353                 return;
354         }
355
356         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
357         if (!item->monitor) {
358                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
359                                 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
360                 return;
361         }
362
363         ret = so_update(item->inst);
364         if (ret < 0) {
365                 ecore_timer_del(item->monitor);
366                 item->monitor = NULL;
367                 reset_widget_updated_flag(item);
368                 return;
369         }
370
371         /*!
372          * \note
373          * Counter of the event monitor is only used for asynchronous content updating,
374          * So reset it to 1 from here because the async updating is started now,
375          * even if it is accumulated by other event function before this.
376          */
377         item->monitor_cnt = 1;
378
379         /*!
380          * \note
381          * While waiting the Callback function call,
382          * Add this for finding the crash
383          */
384         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
385
386         if (ret & WIDGET_NEED_TO_SCHEDULE) {
387                 (void)append_pending_list(item);
388         }
389
390         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
391                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
392                 (void)append_force_update_list(item);
393         }
394
395         if (ret & WIDGET_OUTPUT_UPDATED) {
396                 /*!
397                  * \NOTE 
398                  * In this case, there is potential issue
399                  * 1. User added update CALLBACK -> Inotify event (Only once)
400                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
401                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
402                  *    > Okay. What we want is this.
403                  */
404                 update_monitor_cnt(item);
405         }
406
407         /*
408          * \NOTE
409          * This should be updated after "update_monitor_cnt" function call,
410          * because the update_monitor_cnt function will see the s_info.update variable,
411          */
412         s_info.update_list = eina_list_append(s_info.update_list, item);
413
414         return;
415 }
416
417 static Eina_Bool force_update_cb(void *data)
418 {
419         struct item *item;
420
421         item = eina_list_nth(s_info.force_update_list, 0);
422         if (!item) {
423                 goto cleanout;
424         }
425
426         s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
427
428         do_force_update(item);
429
430         if (s_info.force_update_list) {
431                 return ECORE_CALLBACK_RENEW;
432         }
433
434 cleanout:
435         s_info.force_update_timer = NULL;
436         return ECORE_CALLBACK_CANCEL;
437 }
438
439 static inline __attribute__((always_inline)) int activate_force_update_consumer(void)
440 {
441         if (s_info.force_update_timer) {
442                 return WIDGET_ERROR_NONE;
443         }
444
445         s_info.force_update_timer = ecore_timer_add(0.000001f, force_update_cb, NULL);
446         if (!s_info.force_update_timer) {
447                 ErrPrint("Failed to add a new force update timer\n");
448                 return WIDGET_ERROR_FAULT;
449         }
450
451         DbgPrint("Force update timer is registered\n");
452
453         return WIDGET_ERROR_NONE;
454 }
455
456 static inline void deactivate_force_update_consumer(void)
457 {
458         if (!s_info.force_update_timer) {
459                 return;
460         }
461
462         ecore_timer_del(s_info.force_update_timer);
463         s_info.force_update_timer = NULL;
464
465         DbgPrint("Force update timer is deleted\n");
466 }
467
468 static Eina_Bool pended_cmd_consumer_cb(void *data)
469 {
470         struct item *item;
471
472         item = eina_list_nth(s_info.pending_list, 0);
473         if (!item) {
474                 goto cleanout;
475         }
476
477         if (eina_list_data_find(s_info.update_list, item) || gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
478                 return ECORE_CALLBACK_RENEW;
479         }
480
481         s_info.pending_list = eina_list_remove(s_info.pending_list, item);
482         /*!
483          * \note
484          * To prevent from checking the is_updated function
485          */
486         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
487                 /* item is destroyed */
488         }
489
490         if (s_info.pending_list) {
491                 return ECORE_CALLBACK_RENEW;
492         }
493
494 cleanout:
495         s_info.pending_timer = NULL;
496         s_info.pending_timer_freezed = 0;
497         return ECORE_CALLBACK_CANCEL;
498 }
499
500 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
501 {
502         if (s_info.pending_timer) {
503                 return WIDGET_ERROR_NONE;
504         }
505
506         s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
507         if (!s_info.pending_timer) {
508                 ErrPrint("Failed to add a new pended command consumer\n");
509                 return WIDGET_ERROR_FAULT;
510         }
511
512         /*!
513          * Do not increase the freezed counter.
514          * Just freeze the timer.
515          */
516         if (s_info.pending_timer_freezed) {
517                 ecore_timer_freeze(s_info.pending_timer);
518         }
519
520         return WIDGET_ERROR_NONE;
521 }
522
523 static inline void deactivate_pending_consumer(void)
524 {
525         if (!s_info.pending_timer) {
526                 return;
527         }
528
529         ecore_timer_del(s_info.pending_timer);
530         s_info.pending_timer = NULL;
531         s_info.pending_timer_freezed = 0;
532 }
533
534 static inline void deactivate_gbar_open_pending_consumer(void)
535 {
536         if (!s_info.gbar_open_pending_timer) {
537                 return;
538         }
539
540         ecore_timer_del(s_info.gbar_open_pending_timer);
541         s_info.gbar_open_pending_timer = NULL;
542 }
543
544 static inline int __attribute__((always_inline)) activate_gbar_open_pending_consumer(void)
545 {
546         if (s_info.gbar_open_pending_timer) {
547                 return 0;
548         }
549
550         s_info.gbar_open_pending_timer = ecore_timer_add(0.000001f, gbar_open_pended_cmd_consumer_cb, NULL);
551         if (!s_info.gbar_open_pending_timer) {
552                 ErrPrint("Failed to add a new pended command consumer\n");
553                 return WIDGET_ERROR_FAULT;
554         }
555
556         return 0;
557 }
558
559 static inline void migrate_to_gbar_open_pending_list(const char *pkgname)
560 {
561         Eina_List *l;
562         Eina_List *n;
563         struct item *item;
564         int cnt = 0;
565
566         EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
567                 if (strcmp(pkgname, item->inst->item->pkgname)) {
568                         continue;
569                 }
570
571                 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
572                 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
573                 cnt++;
574         }
575
576         /*!
577          * These items will be moved to the pending list after the GBAR is closed.
578          * Force list -> pd open list -> pending list.
579          * So there is no way to go back to the foce update list again.
580          *
581          * \warning
582          * the ITEM must only exists in one list, pending list or force_update_list
583          * It is not accepted to exists in two list at same time.
584          */
585         EINA_LIST_FOREACH_SAFE(s_info.force_update_list, l, n, item) {
586                 if (strcmp(pkgname, item->inst->item->pkgname)) {
587                         continue;
588                 }
589
590                 s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
591                 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
592                 cnt++;
593         }
594
595         if (s_info.gbar_open_pending_list) {
596                 activate_gbar_open_pending_consumer();
597         }
598
599         if (!s_info.pending_list) {
600                 deactivate_pending_consumer();
601         }
602
603         if (!s_info.force_update_list) {
604                 deactivate_force_update_consumer();
605         }
606 }
607
608 static inline void migrate_to_pending_list(const char *pkgname)
609 {
610         Eina_List *l;
611         Eina_List *n;
612         struct item *item;
613         int cnt = 0;
614
615         EINA_LIST_FOREACH_SAFE(s_info.gbar_open_pending_list, l, n, item) {
616                 if (strcmp(pkgname, item->inst->item->pkgname)) {
617                         continue;
618                 }
619
620                 s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
621                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
622                 cnt++;
623         }
624
625         if (s_info.pending_list) {
626                 activate_pending_consumer();
627         }
628
629         if (!s_info.gbar_open_pending_list) {
630                 deactivate_gbar_open_pending_consumer();
631         }
632 }
633
634 static inline int is_pended_item(struct item *item)
635 {
636         struct item *in_item;
637         if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
638                 in_item = eina_list_data_find(s_info.gbar_open_pending_list, item);
639         } else {
640                 in_item = eina_list_data_find(s_info.pending_list, item);
641         }
642
643         return (in_item == item);
644 }
645
646 static int append_pending_list(struct item *item)
647 {
648         if (item->deleteme) {
649                 DbgPrint("Item will be deleted, ignore update request: %s\n", item->inst->id);
650                 return WIDGET_ERROR_RESOURCE_BUSY;
651         }
652
653         if (eina_list_data_find(s_info.force_update_list, item)) {
654                 DbgPrint("Already exists in force list\n");
655                 return WIDGET_ERROR_NONE;
656         }
657
658         if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
659                 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
660                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
661                         return WIDGET_ERROR_ALREADY_EXIST;
662                 }
663
664                 if (activate_gbar_open_pending_consumer() < 0) {
665                         ErrPrint("Failed to activate GBAR open pending consumer\n");
666                         return WIDGET_ERROR_FAULT;
667                 }
668
669                 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
670         } else {
671                 if (eina_list_data_find(s_info.pending_list, item) == item) {
672                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
673                         return WIDGET_ERROR_ALREADY_EXIST;
674                 }
675
676                 if (IS_WIDGET_SHOWN(item)) {
677                         if (activate_pending_consumer() < 0) {
678                                 return WIDGET_ERROR_FAULT;
679                         }
680
681                         s_info.pending_list = eina_list_append(s_info.pending_list, item);
682                 } else {
683                         if (eina_list_data_find(s_info.hidden_list, item) == item) {
684                                 DbgPrint("Already in hidden list - %s\n", item->inst->item->pkgname);
685                                 return WIDGET_ERROR_ALREADY_EXIST;
686                         }
687
688                         s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
689                 }
690         }
691
692         return WIDGET_ERROR_NONE;
693 }
694
695 static inline int clear_from_pending_list(struct item *item)
696 {
697         Eina_List *l;
698         struct item *tmp;
699
700         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
701                 if (tmp != item) {
702                         continue;
703                 }
704
705                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
706                 if (!s_info.pending_list) {
707                         deactivate_pending_consumer();
708                 }
709                 return WIDGET_ERROR_NONE;
710         }
711
712         return WIDGET_ERROR_NOT_EXIST;
713 }
714
715 static int append_force_update_list(struct item *item)
716 {
717         if (item->deleteme) {
718                 DbgPrint("Item will be deleted, ignore force update request: %s\n", item->inst->id);
719                 return WIDGET_ERROR_RESOURCE_BUSY;
720         }
721
722         /*!
723          * If the item is already in pending list, remove it.
724          */
725         clear_from_pending_list(item);
726
727         if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
728                 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
729                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
730                         return WIDGET_ERROR_ALREADY_EXIST;
731                 }
732
733                 if (activate_gbar_open_pending_consumer() < 0) {
734                         ErrPrint("Failed to activate GBAR open pending consumer\n");
735                         return WIDGET_ERROR_FAULT;
736                 }
737
738                 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
739         } else {
740                 if (eina_list_data_find(s_info.force_update_list, item)) {
741                         DbgPrint("Already in force update list\n");
742                         return WIDGET_ERROR_NONE;
743                 }
744
745                 if (IS_WIDGET_SHOWN(item)) {
746                         if (activate_force_update_consumer() < 0) {
747                                 return WIDGET_ERROR_FAULT;
748                         }
749
750                         s_info.force_update_list = eina_list_append(s_info.force_update_list, item);
751                 } else {
752                         if (eina_list_data_find(s_info.hidden_list, item) == item) {
753                                 DbgPrint("Already in hidden list - %s\n", item->inst->id);
754                                 return WIDGET_ERROR_ALREADY_EXIST;
755                         }
756
757                         s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
758
759                         DbgPrint("forced item is moved to hidden_list - %s\n", item->inst->id);
760                 }
761         }
762
763         return WIDGET_ERROR_NONE;
764 }
765
766 static inline int clear_from_force_update_list(struct item *item)
767 {
768         Eina_List *l;
769         struct item *tmp;
770
771         EINA_LIST_FOREACH(s_info.force_update_list, l, tmp) {
772                 if (tmp != item) {
773                         continue;
774                 }
775
776                 s_info.force_update_list = eina_list_remove_list(s_info.force_update_list, l);
777                 if (!s_info.force_update_list) {
778                         deactivate_force_update_consumer();
779                 }
780
781                 return WIDGET_ERROR_NONE;
782         }
783
784         return WIDGET_ERROR_NOT_EXIST;
785 }
786
787 static inline void migrate_to_pending_list_from_hidden_list(struct item *item)
788 {
789         if (!eina_list_data_find(s_info.hidden_list, item)) {
790                 return;
791         }
792
793         s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
794         append_pending_list(item);
795 }
796
797 /*!
798  * \brief
799  *   This function can call the update callback
800  * return 0 if there is no changes
801  * return -1 the item is deleted
802  */
803 static inline int timer_thaw(struct item *item)
804 {
805         double pending;
806         double period;
807         double delay;
808         double sleep_time;
809
810         if (!item->timer) {
811                 return 0;
812         }
813
814         ecore_timer_thaw(item->timer);
815         period = ecore_timer_interval_get(item->timer);
816         pending = ecore_timer_pending_get(item->timer);
817         delay = util_time_delay_for_compensation(period) - pending;
818         ecore_timer_delay(item->timer, delay);
819
820         if (item->sleep_at == 0.0f) {
821                 return 0;
822         }
823
824         sleep_time = util_timestamp() - item->sleep_at;
825         item->sleep_at = 0.0f;
826
827         if (sleep_time > pending) {
828
829                 /*!
830                  * Before do updating forcely, clear it from the pending list.
831                  * We will consume it from here now.
832                  */
833                 (void)clear_from_pending_list(item);
834
835                 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
836                         /* item is destroyed */
837                         return UPDATE_ITEM_DELETED;
838                 } else {
839                         return UPDATE_INVOKED;
840                 }
841         }
842
843         return UPDATE_NOT_INVOKED;
844 }
845
846 static void timer_freeze(struct item *item)
847 {
848         if (!item->timer) {
849                 return;
850         }
851
852         ecore_timer_freeze(item->timer);
853
854         if (ecore_timer_interval_get(item->timer) <= 1.0f) {
855                 return;
856         }
857
858 #if defined(_USE_ECORE_TIME_GET)
859         item->sleep_at = ecore_time_get();
860 #else
861         struct timeval tv;
862         if (gettimeofday(&tv, NULL) < 0) {
863                 ErrPrint("gettimeofday: %d\n", errno);
864                 tv.tv_sec = 0;
865                 tv.tv_usec = 0;
866         }
867
868         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
869 #endif
870 }
871
872 static inline Eina_List *find_item(struct instance *inst)
873 {
874         Eina_List *l;
875         struct item *item;
876
877         EINA_LIST_FOREACH(s_info.item_list, l, item) {
878                 if (item->inst == inst) {
879                         return l;
880                 }
881         }
882
883         return NULL;
884 }
885
886 static int desc_updated_cb(const char *filename, void *data, int over)
887 {
888         struct item *item;
889
890         if (over) {
891                 WarnPrint("Event Q overflow\n");
892         }
893
894         item = data;
895
896         DbgPrint("DESC %s is updated\n", filename);
897         if (item->is_gbar_show) {
898                 widget_damage_region_s region = {
899                         .x = 0,
900                         .y = 0,
901                         .w = item->inst->w,
902                         .h = item->inst->h,
903                 };
904
905                 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, &region, 1, filename);
906         } else {
907                 ErrPrint("But GBAR is not opened, Ignore this update (%s)\n", item->inst->id);
908         }
909         return EXIT_SUCCESS;
910 }
911
912 static inline int output_handler(struct item *item)
913 {
914         int invalid = 0;
915
916         item->monitor_cnt--;
917         if (item->monitor_cnt < 0 || item->heavy_updating) {
918                 if (!item->heavy_updating) {
919                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
920                         invalid = 1;
921                 } else {
922                         item->heavy_updating = 0;       /* Reset flag */
923                 }
924
925                 item->monitor_cnt = 0;
926         }
927
928         if (item->monitor_cnt == 0) {
929                 if (!invalid) {
930                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
931                 }
932
933                 if (item->monitor) {
934                         ecore_timer_del(item->monitor);
935                         item->monitor = NULL;
936                 }
937
938                 s_info.update_list = eina_list_remove(s_info.update_list, item);
939
940                 if (item->deleteme) {
941                         update_monitor_del(item->inst->id, item);
942                         widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
943                         (void)so_destroy(item->inst, item->unload_so);
944                         free(item);
945                         return EXIT_FAILURE;
946                 }
947         }
948
949         return EXIT_SUCCESS;
950 }
951
952 static int file_updated_cb(const char *filename, void *data, int over)
953 {
954         struct item *item;
955         int w;
956         int h;
957         double priority;
958         char *content = NULL;
959         char *title = NULL;
960         int ret;
961         char *icon = NULL;
962         char *name = NULL;
963
964         if (over) {
965                 WarnPrint("Event Q overflow\n");
966         }
967
968         item = data;
969
970         if (item->deleteme) {
971                 DbgPrint("Item is in deleting process. (%s)\n", filename);
972                 goto out;
973         }
974
975         ESTIMATE_START(item->inst->id);
976
977         ret = util_get_filesize(filename);
978         if (ret <= 0) {
979                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
980                 ESTIMATE_END(item->inst->id);
981                 return EXIT_SUCCESS; /*!< To keep the callback */
982         }
983
984         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
985         if (ret < 0) {
986                 ErrPrint("widget_get_info returns %d\n", ret);
987                 ESTIMATE_END(item->inst->id);
988                 return EXIT_SUCCESS; /*!< To keep the callback */
989         }
990
991         /**
992          * Alternative information can be NOT_IMPLEMENTED
993          * And we can ignore its error.
994          */
995         ret = so_get_alt_info(item->inst, &icon, &name);
996         if (ret < 0) {
997                 ErrPrint("widget_get_alt_info returns %d (ignored)\n", ret);
998         }
999
1000         if (IS_WIDGET_SHOWN(item)) {
1001                 widget_damage_region_s region = {
1002                         .x = 0,
1003                         .y = 0,
1004                         .w = item->inst->w,
1005                         .h = item->inst->h,
1006                 };
1007                 /**
1008                  * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1009                  * We cannot use the direct path for sending updated event.
1010                  */
1011                 widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1012                                 content, title, item->inst->icon, item->inst->name);
1013                 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, &region, 0, NULL);
1014         } else {
1015                 item->is_widget_updated++;
1016         }
1017
1018         ESTIMATE_END(item->inst->id);
1019 out:
1020         return output_handler(item);
1021 }
1022
1023 static void reset_widget_updated_flag(struct item *item)
1024 {
1025         widget_damage_region_s region = {
1026                 .x = 0,
1027                 .y = 0,
1028                 .w = item->inst->w,
1029                 .h = item->inst->h,
1030         };
1031
1032         if (!item->is_widget_updated) {
1033                 return;
1034         }
1035
1036         DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
1037                         item->inst->id, item->is_widget_updated,
1038                         item->inst->content, item->inst->title);
1039
1040         /**
1041          * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1042          * We cannot use the direct path for sending updated event.
1043          */
1044         widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1045                         item->inst->content, item->inst->title, item->inst->icon, item->inst->name);
1046         widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, &region, 0, NULL);
1047
1048         item->is_widget_updated = 0;
1049 }
1050
1051 static inline int clear_from_gbar_open_pending_list(struct item *item)
1052 {
1053         Eina_List *l;
1054         struct item *tmp;
1055
1056         EINA_LIST_FOREACH(s_info.gbar_open_pending_list, l, tmp) {
1057                 if (tmp != item) {
1058                         continue;
1059                 }
1060
1061                 s_info.gbar_open_pending_list = eina_list_remove_list(s_info.gbar_open_pending_list, l);
1062                 if (!s_info.gbar_open_pending_list) {
1063                         deactivate_gbar_open_pending_consumer();
1064                 }
1065                 return WIDGET_ERROR_NONE;
1066         }
1067
1068         return WIDGET_ERROR_NOT_EXIST;
1069 }
1070
1071 /*!
1072  * \note
1073  * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
1074  * So every caller, should manage the deleted item correctly.
1075  */
1076 static Eina_Bool updator_cb(void *data)
1077 {
1078         struct item *item;
1079         int ret;
1080
1081         item = data;
1082
1083         if (item->monitor) { /*!< If this item is already in update process */
1084                 return ECORE_CALLBACK_RENEW;
1085         }
1086
1087         if (!IS_WIDGET_SHOWN(item)) {
1088                 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
1089                 (void)append_pending_list(item);
1090                 return ECORE_CALLBACK_RENEW;
1091         }
1092
1093         if (item->state != STATE_RESUMED) {
1094                 item->updated_in_pause++;
1095                 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
1096                 return ECORE_CALLBACK_RENEW;
1097         }
1098
1099         item->updated_in_pause = 0;
1100
1101         ret = so_is_updated(item->inst);
1102         if (ret <= 0) {
1103                 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
1104                         widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
1105                         widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
1106                         /*!
1107                          * \CRITICAL
1108                          * Every caller of this, must not access the item from now.
1109                          */
1110                         return ECORE_CALLBACK_CANCEL;
1111                 }
1112
1113                 reset_widget_updated_flag(item);
1114                 return ECORE_CALLBACK_RENEW;
1115         }
1116
1117         /*!
1118          * \note
1119          * Check the update_list, if you want make serialized update
1120          */
1121         if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
1122                 DbgPrint("%s is busy\n", item->inst->id);
1123                 (void)append_pending_list(item);
1124                 return ECORE_CALLBACK_RENEW;
1125         }
1126
1127         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
1128         if (!item->monitor) {
1129                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
1130                                 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
1131                 return ECORE_CALLBACK_RENEW;
1132         }
1133
1134         ret = so_update(item->inst);
1135         if (ret < 0) {
1136                 ecore_timer_del(item->monitor);
1137                 item->monitor = NULL;
1138                 reset_widget_updated_flag(item);
1139                 return ECORE_CALLBACK_RENEW;
1140         }
1141
1142         /*!
1143          * \note
1144          * Counter of the event monitor is only used for asynchronous content updating,
1145          * So reset it to 1 from here because the async updating is started now,
1146          * even if it is accumulated by other event function before this.
1147          */
1148         item->monitor_cnt = 1;
1149
1150         /*!
1151          * \note
1152          * While waiting the Callback function call,
1153          * Add this for finding the crash
1154          */
1155         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
1156
1157         if (ret & WIDGET_NEED_TO_SCHEDULE) {
1158                 (void)append_pending_list(item);
1159         }
1160
1161         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1162                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
1163                 (void)append_force_update_list(item);
1164         }
1165
1166         if (ret & WIDGET_OUTPUT_UPDATED) {
1167                 /*!
1168                  * \NOTE 
1169                  * In this case, there is potential issue
1170                  * 1. User added update CALLBACK -> Inotify event (Only once)
1171                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
1172                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
1173                  *    > Okay. What we want is this.
1174                  */
1175                 update_monitor_cnt(item);
1176         }
1177
1178         /*
1179          * \NOTE
1180          * This should be updated after "update_monitor_cnt" function call,
1181          * because the update_monitor_cnt function will see the s_info.update variable,
1182          */
1183         s_info.update_list = eina_list_append(s_info.update_list, item);
1184
1185         return ECORE_CALLBACK_RENEW;
1186 }
1187
1188 static inline void update_monitor_del(const char *id, struct item *item)
1189 {
1190         char *tmp;
1191         int len;
1192
1193         tmp = (char *)util_uri_to_path(id);
1194         if (!tmp) {
1195                 ErrPrint("Invalid parameter\n");
1196                 return;
1197         }
1198
1199         update_monitor_del_update_cb(tmp, file_updated_cb);
1200
1201         len = strlen(tmp) + strlen(".desc") + 1;
1202         tmp = malloc(len);
1203         if (!tmp) {
1204                 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1205                 return;
1206         }
1207
1208         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
1209         update_monitor_del_update_cb(tmp, desc_updated_cb);
1210         free(tmp);
1211 }
1212
1213 static inline int add_desc_update_monitor(const char *id, struct item *item)
1214 {
1215         char *filename;
1216         int len;
1217         int ret;
1218
1219         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
1220         filename = malloc(len);
1221         if (!filename) {
1222                 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1223                 return WIDGET_ERROR_OUT_OF_MEMORY;
1224         }
1225
1226         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
1227         ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
1228         free(filename);
1229         return ret;
1230 }
1231
1232 static inline int add_file_update_monitor(const char *id, struct item *item)
1233 {
1234         return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
1235 }
1236
1237 static inline int update_monitor_add(const char *id, struct item *item)
1238 {
1239         /*!
1240          * \NOTE
1241          * item->inst is not available yet.
1242          */
1243         add_file_update_monitor(id, item);
1244         add_desc_update_monitor(id, item);
1245         return WIDGET_ERROR_NONE;
1246 }
1247
1248 static int disconnected_cb(int handle, void *data)
1249 {
1250         Eina_List *l;
1251         Eina_List *k;
1252         Eina_List *n;
1253         struct item *item;
1254         struct connection *connection;
1255         struct connection *conn_handle;
1256
1257         connection = connection_find_by_fd(handle);
1258         if (!connection) {
1259                 return 0;
1260         }
1261
1262         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1263                 EINA_LIST_FOREACH_SAFE(item->direct_path_list, k, n, conn_handle) {
1264                         if (conn_handle == connection) {
1265                                 item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
1266                                 (void)connection_unref(conn_handle);
1267                         }
1268                 }
1269         }
1270
1271         return 0;
1272 }
1273
1274 HAPI void widget_viewer_init(void)
1275 {
1276         int ret;
1277         ret = connection_add_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb, NULL);
1278         if (ret < 0) {
1279                 ErrPrint("Unable to add an event handler\n");
1280         }
1281         return;
1282 }
1283
1284 HAPI void widget_viewer_fini(void)
1285 {
1286         int ret;
1287
1288         ret = widget_delete_all_deleteme();
1289         if (ret < 0) {
1290                 DbgPrint("Delete all deleteme: %d\n", ret);
1291         }
1292
1293         ret = widget_delete_all();
1294         if (ret < 0) {
1295                 DbgPrint("Delete all: %d\n", ret);
1296         }
1297
1298         /* Just for in case of ... */
1299         deactivate_pending_consumer();
1300         deactivate_gbar_open_pending_consumer();
1301
1302         eina_list_free(s_info.gbar_open_pending_list);
1303         s_info.gbar_open_pending_list = NULL;
1304         eina_list_free(s_info.pending_list);
1305         s_info.pending_list = NULL;
1306
1307         (void)connection_del_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb);
1308         return;
1309 }
1310
1311 /*!
1312  * \note
1313  * Exported API for each widgetes.
1314  */
1315 int widget_send_updated(const char *pkgname, const char *id, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
1316 {
1317         Eina_List *l;
1318         struct item *item;
1319         int ret = WIDGET_ERROR_NOT_EXIST;
1320         widget_damage_region_s region = {
1321                 .x = x,
1322                 .y = y,
1323                 .w = w,
1324                 .h = h,
1325         };
1326
1327         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1328                 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1329                         continue;
1330                 }
1331
1332                 if (item->direct_path_list) {
1333                         Eina_List *l;
1334                         struct connection *conn_handle;
1335                         EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1336                                 ret = widget_provider_send_direct_updated(connection_handle(conn_handle), pkgname, id, idx, &region, gbar, descfile);
1337                         }
1338                 } else {
1339                         ret = widget_provider_send_updated(pkgname, id, idx, &region, gbar, descfile);
1340                 }
1341
1342                 break;
1343         }
1344
1345         return ret;
1346 }
1347
1348 int widget_send_buffer_updated(const char *pkgname, const char *id, widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
1349 {
1350         Eina_List *l;
1351         struct item *item;
1352         int ret = WIDGET_ERROR_NOT_EXIST;
1353         widget_damage_region_s region = {
1354                 .x = x,
1355                 .y = y,
1356                 .w = w,
1357                 .h = h,
1358         };
1359
1360         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1361                 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1362                         continue;
1363                 }
1364
1365                 if (item->direct_path_list) {
1366                         Eina_List *l;
1367                         struct connection *conn_handle;
1368                         EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1369                                 ret = widget_provider_send_direct_buffer_updated(connection_handle(conn_handle), handle, idx, &region, gbar, descfile);
1370                         }
1371                 } else {
1372                         ret = widget_provider_send_buffer_updated(handle, idx, &region, gbar, descfile);
1373                 }
1374
1375                 break;
1376         }
1377
1378         return ret;
1379 }
1380
1381 const char *widget_find_pkgname(const char *filename)
1382 {
1383         Eina_List *l;
1384         struct item *item;
1385
1386         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1387                 if (!strcmp(item->inst->id, filename)) {
1388                         return item->inst->item->pkgname;
1389                 }
1390         }
1391
1392         return NULL;
1393 }
1394
1395 int widget_update_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1396 {
1397         Eina_List *l;
1398         struct item *item;
1399
1400         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1401                 if (!strcmp(item->inst->id, id)) {
1402                         if (content && strlen(content)) {
1403                                 char *_content;
1404
1405                                 _content = strdup(content);
1406                                 if (_content) {
1407                                         if (item->inst->content) {
1408                                                 free(item->inst->content);
1409                                                 item->inst->content = NULL;
1410                                         }
1411
1412                                         item->inst->content = _content;
1413                                 } else {
1414                                         ErrPrint("strdup: %d\n", errno);
1415                                 }
1416                         }
1417
1418                         if (title && strlen(title)) {
1419                                 char *_title;
1420
1421                                 _title = strdup(title);
1422                                 if (_title) {
1423                                         if (item->inst->title) {
1424                                                 free(item->inst->title);
1425                                                 item->inst->title = NULL;
1426                                         }
1427
1428                                         item->inst->title = _title;
1429                                 } else {
1430                                         ErrPrint("strdup: %d\n", errno);
1431                                 }
1432                         }
1433
1434                         if (icon && strlen(icon)) {
1435                                 char *_icon;
1436
1437                                 _icon = strdup(icon);
1438                                 if (_icon) {
1439                                         if (item->inst->icon) {
1440                                                 free(item->inst->icon);
1441                                                 item->inst->icon = NULL;
1442                                         }
1443
1444                                         item->inst->icon = _icon;
1445                                 } else {
1446                                         ErrPrint("strdup: %d\n", errno);
1447                                 }
1448                         }
1449
1450                         if (name && strlen(name)) {
1451                                 char *_name;
1452
1453                                 _name = strdup(name);
1454                                 if (_name) {
1455                                         if (item->inst->name) {
1456                                                 free(item->inst->name);
1457                                                 item->inst->name = NULL;
1458                                         }
1459
1460                                         item->inst->name = _name;
1461                                 } else {
1462                                         ErrPrint("strdup: %d\n", errno);
1463                                 }
1464                         }
1465
1466                         return WIDGET_ERROR_NONE;
1467                 }
1468         }
1469
1470         return WIDGET_ERROR_NOT_EXIST;
1471 }
1472
1473 int widget_request_update_by_id(const char *filename)
1474 {
1475         Eina_List *l;
1476         struct item *item;
1477
1478         if (so_current_op() != WIDGET_OP_UNKNOWN) {
1479                 ErrPrint("Current operation: %d\n", so_current_op());
1480                 /*!
1481                  * \note
1482                  * Some case requires to update the content of other widget from widget_XXX ABI.
1483                  * In that case this function can be used so we have not to filter it from here.
1484                  * ex) Setting accessibility.
1485                  * Press the assistive light, turned on, need to update other instances too.
1486                  * Then the widget will use this function from widget_clicked function.
1487                  */
1488         }
1489
1490         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1491                 if (!strcmp(item->inst->id, filename)) {
1492                         return append_pending_list(item);
1493                 }
1494         }
1495
1496         return WIDGET_ERROR_NOT_EXIST;
1497 }
1498
1499 int widget_trigger_update_monitor(const char *filename, int is_gbar)
1500 {
1501         char *fname;
1502         int ret;
1503
1504         if (so_current_op() != WIDGET_OP_UNKNOWN) {
1505                 ErrPrint("Current operation: %d\n", so_current_op());
1506                 return WIDGET_ERROR_INVALID_PARAMETER;
1507         }
1508
1509         if (is_gbar) {
1510                 int len;
1511                 len = strlen(filename) + strlen(".desc");
1512
1513                 fname = malloc(len + 1);
1514                 if (!fname) {
1515                         ErrPrint("malloc: %d\n", errno);
1516                         return WIDGET_ERROR_OUT_OF_MEMORY;
1517                 }
1518
1519                 snprintf(fname, len, "%s.desc", filename);
1520         } else {
1521                 fname = strdup(filename);
1522                 if (!fname) {
1523                         ErrPrint("strdup: %d\n", errno);
1524                         return WIDGET_ERROR_OUT_OF_MEMORY;
1525                 }
1526         }
1527
1528         if (access(fname, R_OK | W_OK) != 0) {
1529                 ErrPrint("access: %s (%d)\n", fname, errno);
1530                 ret = WIDGET_ERROR_IO_ERROR;
1531         } else {
1532                 ret = update_monitor_trigger_update_cb(fname, 0);
1533         }
1534
1535         free(fname);
1536         return ret;
1537 }
1538
1539 HAPI int widget_open_gbar(const char *pkgname, const char *id)
1540 {
1541         struct instance *inst;
1542         struct instance *tmp;
1543         Eina_List *l;
1544
1545         inst = so_find_instance(pkgname, id);
1546         if (!inst) {
1547                 ErrPrint("Instance is not found\n");
1548                 return WIDGET_ERROR_NOT_EXIST;
1549         }
1550
1551         EINA_LIST_FOREACH(s_info.gbar_list, l, tmp) {
1552                 if (tmp == inst) {
1553                         return 0;
1554                 }
1555         }
1556
1557         if (!s_info.gbar_list) {
1558                 pending_timer_freeze();
1559
1560                 /*!
1561                  * \note
1562                  * Freeze the force timer only in this case.
1563                  */
1564                 force_timer_freeze();
1565         }
1566
1567         s_info.gbar_list = eina_list_append(s_info.gbar_list, inst);
1568
1569         /*!
1570          * Find all instances from the pending list.
1571          * Move them to gbar_open_pending_timer
1572          */
1573         migrate_to_gbar_open_pending_list(pkgname);
1574         return WIDGET_ERROR_NONE;
1575 }
1576
1577 HAPI int widget_close_gbar(const char *pkgname, const char *id)
1578 {
1579         Eina_List *l;
1580         Eina_List *n;
1581         struct instance *tmp;
1582         struct instance *inst;
1583
1584         inst = so_find_instance(pkgname, id);
1585         if (!inst) {
1586                 ErrPrint("Insatnce is not found\n");
1587                 return WIDGET_ERROR_NOT_EXIST;
1588         }
1589
1590         EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1591                 if (tmp != inst) {
1592                         continue;
1593                 }
1594
1595                 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1596                 if (!s_info.gbar_list) {
1597                         pending_timer_thaw();
1598                         force_timer_thaw();
1599                 }
1600
1601                 /*!
1602                  * Move all items in gbar_open_pending_list
1603                  * to pending_list.
1604                  */
1605                 migrate_to_pending_list(pkgname);
1606                 return WIDGET_ERROR_NONE;
1607         }
1608
1609         return WIDGET_ERROR_NOT_EXIST;
1610 }
1611
1612 static struct method s_table[] = {
1613         {
1614                 .cmd = NULL,
1615                 .handler = NULL,
1616         },
1617 };
1618
1619 HAPI int widget_create(const char *pkgname, const char *id, struct widget_create_arg *arg, int *w, int *h, double *priority, char **content, char **title)
1620 {
1621         struct instance *inst;
1622         struct item *item;
1623         int ret;
1624         int create_ret;
1625         int need_to_create;
1626
1627         need_to_create = 0;
1628         *content = NULL;
1629         *title = NULL;
1630
1631         inst = so_find_instance(pkgname, id);
1632         if (inst) {
1633                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1634                 return WIDGET_ERROR_NONE;
1635         }
1636
1637         if (!arg->skip_need_to_create) {
1638                 ret = so_create_needed(pkgname, arg->cluster, arg->category, arg->abi);
1639                 if (ret != WIDGET_NEED_TO_CREATE) {
1640                         return WIDGET_ERROR_PERMISSION_DENIED;
1641                 }
1642
1643                 need_to_create = 1;
1644         }
1645
1646         item = calloc(1, sizeof(*item));
1647         if (!item) {
1648                 ErrPrint("calloc: %d (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", errno, pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1649                 return WIDGET_ERROR_OUT_OF_MEMORY;
1650         }
1651
1652         ret = update_monitor_add(id, item);
1653         if (ret < 0) {
1654                 free(item);
1655                 return ret;
1656         }
1657
1658         if (arg->direct_addr) {
1659                 struct connection *conn_handle;
1660
1661                 conn_handle = connection_find_by_addr(arg->direct_addr);
1662                 if (!conn_handle) {
1663                         conn_handle = connection_create(arg->direct_addr, (void *)s_table);
1664                         if (!conn_handle) {
1665                                 ErrPrint("Direct update-path is not supported\n");
1666                         } else {
1667                                 DbgPrint("Direct update-path is created: %s\n", id);
1668                                 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
1669                         }
1670                 } else {
1671                         item->direct_path_list = eina_list_append(item->direct_path_list, connection_ref(conn_handle));
1672                         DbgPrint("Direct update-path is referred: %s\n", id);
1673                 }
1674         }
1675
1676         create_ret = so_create(pkgname, id, arg->content, arg->timeout, arg->has_widget_script, arg->cluster, arg->category, arg->abi, &inst);
1677         if (create_ret < 0) {
1678                 struct connection *conn_handle;
1679
1680                 update_monitor_del(id, item);
1681                 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1682                         (void)connection_unref(conn_handle);
1683                 }
1684                 free(item);
1685
1686                 *w = 0;
1687                 *h = 0;
1688                 *priority = 0.0f;
1689                 return create_ret;
1690         }
1691
1692         item->inst = inst;
1693         item->state = STATE_UNKNOWN;
1694
1695         if (arg->period > 0.0f && !s_info.secured) {
1696                 item->timer = util_timer_add(arg->period, updator_cb, item);
1697                 if (!item->timer) {
1698                         struct connection *conn_handle;
1699                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1700                         update_monitor_del(id, item);
1701                         EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1702                                 (void)connection_unref(conn_handle);
1703                         }
1704                         (void)so_destroy(inst, item->unload_so);
1705                         free(item);
1706                         return WIDGET_ERROR_FAULT;
1707                 }
1708
1709                 if (s_info.state == STATE_PAUSED) {
1710                         timer_freeze(item);
1711                 }
1712         } else {
1713                 DbgPrint("Local update timer is disabled: %lf (%d)\n", arg->period, s_info.secured);
1714                 item->timer = NULL;
1715         }
1716
1717         s_info.item_list = eina_list_append(s_info.item_list, item);
1718
1719         if (create_ret & WIDGET_NEED_TO_SCHEDULE) {
1720                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1721                 (void)append_pending_list(item);
1722         }
1723
1724         if (create_ret & WIDGET_FORCE_TO_SCHEDULE) {
1725                 DbgPrint("%s Returns WIDGET_NEED_TO_FORCE_UPDATE\n", pkgname);
1726                 (void)append_force_update_list(item);
1727         }
1728
1729         if (create_ret & WIDGET_OUTPUT_UPDATED) {
1730                 update_monitor_cnt(item);
1731                 /*!
1732                  * \note
1733                  * To send a output info, get the info forcely.
1734                  * but the output file monitor will do this again
1735                  *
1736                  * This function will set the tmp_content and tmp_title
1737                  * even if it has no updates on the content, title,
1738                  * it will set them to NULL.
1739                  */
1740                 if (so_get_output_info(inst, w, h, priority, content, title) == (int)WIDGET_ERROR_NONE) {
1741                         if (*content) {
1742                                 char *tmp;
1743
1744                                 tmp = strdup(*content);
1745                                 if (!tmp) {
1746                                         ErrPrint("strdup: %d\n", errno);
1747                                 }
1748
1749                                 *content = tmp;
1750                         }
1751
1752                         if (*title) {
1753                                 char *tmp;
1754
1755                                 tmp = strdup(*title);
1756                                 if (!tmp) {
1757                                         ErrPrint("strdup: %d\n", errno);
1758                                 }
1759
1760                                 *title = tmp;
1761                         }
1762                 }
1763         }
1764
1765         *w = inst->w;
1766         *h = inst->h;
1767         *priority = inst->priority;
1768         return need_to_create;
1769 }
1770
1771 HAPI int widget_destroy(const char *pkgname, const char *id, int type)
1772 {
1773         Eina_List *l;
1774         Eina_List *n;
1775         struct instance *inst;
1776         struct instance *tmp;
1777         struct item *item;
1778         struct connection *conn_handle;
1779
1780         inst = so_find_instance(pkgname, id);
1781         if (!inst) {
1782                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1783                 return WIDGET_ERROR_INVALID_PARAMETER;
1784         }
1785
1786         EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1787                 if (tmp != inst) {
1788                         continue;
1789                 }
1790
1791                 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1792                 if (!s_info.gbar_list) {
1793                         pending_timer_thaw();
1794                         force_timer_thaw();
1795                 }
1796
1797                 /*!
1798                  * Move all items in gbar_open_pending_list
1799                  * to pending_list.
1800                  */
1801                 migrate_to_pending_list(pkgname);
1802                 break;
1803         }
1804
1805         l = find_item(inst);
1806         if (!l) {
1807                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1808                 return WIDGET_ERROR_NOT_EXIST;
1809         }
1810
1811         item = eina_list_data_get(l);
1812         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1813
1814         s_info.update_list = eina_list_remove(s_info.update_list, item);
1815         s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
1816         clear_from_gbar_open_pending_list(item);
1817         clear_from_pending_list(item);
1818         clear_from_force_update_list(item);
1819         EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1820                 (void)connection_unref(conn_handle);
1821         }
1822
1823         if (item->timer) {
1824                 ecore_timer_del(item->timer);
1825                 item->timer = NULL;
1826         }
1827
1828         /*
1829          * To keep the previous status, we should or'ing the value.
1830          */
1831         item->unload_so = (item->unload_so || (type == WIDGET_DESTROY_TYPE_UNINSTALL) || (type == WIDGET_DESTROY_TYPE_UPGRADE));
1832
1833         if (item->monitor) {
1834                 item->deleteme = 1;
1835         } else {
1836                 update_monitor_del(id, item);
1837                 (void)so_destroy(inst, item->unload_so);
1838                 free(item);
1839         }
1840
1841         return WIDGET_ERROR_NONE;
1842 }
1843
1844 HAPI int widget_viewer_resize_widget(const char *pkgname, const char *id, int w, int h)
1845 {
1846         Eina_List *l;
1847         struct instance *inst;
1848         struct item *item;
1849         int ret;
1850
1851         inst = so_find_instance(pkgname, id);
1852         if (!inst) {
1853                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1854                 return WIDGET_ERROR_INVALID_PARAMETER;
1855         }
1856
1857         l = find_item(inst);
1858         if (!l) {
1859                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1860                 return WIDGET_ERROR_NOT_EXIST;
1861         }
1862
1863         item = eina_list_data_get(l);
1864
1865         ESTIMATE_START(id);
1866         ret = so_resize(inst, w, h);
1867         ESTIMATE_END(id);
1868         if (ret < 0) {
1869                 return ret;
1870         }
1871
1872         if (ret & WIDGET_NEED_TO_SCHEDULE) {
1873                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1874                 (void)append_pending_list(item);
1875         }
1876
1877         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1878                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1879                 (void)append_force_update_list(item);
1880         }
1881
1882         if (ret & WIDGET_OUTPUT_UPDATED) {
1883                 update_monitor_cnt(item);
1884         }
1885
1886         return WIDGET_ERROR_NONE;
1887 }
1888
1889 HAPI char *widget_pinup(const char *pkgname, const char *id, int pinup)
1890 {
1891         struct instance *inst;
1892         char *ret;
1893
1894         inst = so_find_instance(pkgname, id);
1895         if (!inst) {
1896                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1897                 return NULL;
1898         }
1899
1900         ret = so_pinup(inst, pinup);
1901         return ret;
1902 }
1903
1904 HAPI int widget_viewer_set_period(const char *pkgname, const char *id, double period)
1905 {
1906         Eina_List *l;
1907         struct instance *inst;
1908         struct item *item;
1909
1910         inst = so_find_instance(pkgname, id);
1911         if (!inst) {
1912                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1913                 return WIDGET_ERROR_INVALID_PARAMETER;
1914         }
1915
1916         l = find_item(inst);
1917         if (!l) {
1918                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1919                 return WIDGET_ERROR_NOT_EXIST;
1920         }
1921
1922         item = eina_list_data_get(l);
1923
1924         if (period <= 0.0f) {
1925                 if (item->timer) {
1926                         ecore_timer_del(item->timer);
1927                         item->timer = NULL;
1928                 }
1929         } else {
1930                 if (item->timer) {
1931                         util_timer_interval_set(item->timer, period);
1932                 } else if (!s_info.secured) {
1933                         item->timer = util_timer_add(period, updator_cb, item);
1934                         if (!item->timer) {
1935                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1936                                 return WIDGET_ERROR_FAULT;
1937                         }
1938
1939                         if (s_info.state == STATE_PAUSED) {
1940                                 timer_freeze(item);
1941                         }
1942                 }
1943         }
1944
1945         return WIDGET_ERROR_NONE;
1946 }
1947
1948 HAPI int widget_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1949 {
1950         Eina_List *l;
1951         struct instance *inst;
1952         struct item *item;
1953         int ret;
1954
1955         inst = so_find_instance(pkgname, id);
1956         if (!inst) {
1957                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1958                 return WIDGET_ERROR_INVALID_PARAMETER;
1959         }
1960
1961         l = find_item(inst);
1962         if (!l) {
1963                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1964                 return WIDGET_ERROR_NOT_EXIST;
1965         }
1966
1967         item = eina_list_data_get(l);
1968
1969         ESTIMATE_START(id);
1970         ret = so_clicked(inst, event, timestamp, x, y);
1971         ESTIMATE_END(id);
1972         if (ret < 0) {
1973                 return ret;
1974         }
1975
1976         if (ret & WIDGET_NEED_TO_SCHEDULE) {
1977                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1978                 (void)append_pending_list(item);
1979         }
1980
1981         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1982                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1983                 (void)append_force_update_list(item);
1984         }
1985
1986         if (ret & WIDGET_OUTPUT_UPDATED) {
1987                 update_monitor_cnt(item);
1988         }
1989
1990         return WIDGET_ERROR_NONE;
1991 }
1992
1993 HAPI int widget_script_event(const char *pkgname, const char *id, const char *signal_name, const char *source, widget_event_info_s event_info)
1994 {
1995         Eina_List *l;
1996         struct instance *inst;
1997         struct item *item;
1998         int ret;
1999
2000         inst = so_find_instance(pkgname, id);
2001         if (!inst) {
2002                 ErrPrint("Instance %s - %s is not exists (signal_name[%s], source[%s])\n", pkgname, id, signal_name, source);
2003                 return WIDGET_ERROR_INVALID_PARAMETER;
2004         }
2005
2006         l = find_item(inst);
2007         if (!l) {
2008                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, signal_name, source);
2009                 return WIDGET_ERROR_NOT_EXIST;
2010         }
2011
2012         item = eina_list_data_get(l);
2013
2014         if (signal_name && source && !strcmp(source, id)) {
2015                 if (item->inst->item->has_widget_script) {
2016                         if (!strcmp(signal_name, "widget,show")) {
2017                                 item->is_widget_show = 1;
2018
2019                                 migrate_to_pending_list_from_hidden_list(item);
2020
2021                                 if (item->is_widget_updated && !is_pended_item(item)) {
2022                                         reset_widget_updated_flag(item);
2023                                 }
2024
2025                                 source = util_uri_to_path(source);
2026                         } else if (!strcmp(signal_name, "widget,hide")) {
2027                                 DbgPrint("Livebox(%s) script is hide now\n", id);
2028                                 item->is_widget_show = 0;
2029
2030                                 source = util_uri_to_path(source);
2031                         }
2032                 }
2033
2034                 if (!strcmp(signal_name, "gbar,show")) {
2035                         item->is_gbar_show = 1;
2036                         source = util_uri_to_path(source);
2037                 } else if (!strcmp(signal_name, "gbar,hide")) {
2038                         item->is_gbar_show = 0;
2039                         source = util_uri_to_path(source);
2040                 }
2041         }
2042
2043         ESTIMATE_START(id);
2044         ret = so_script_event(inst, signal_name, source, event_info);
2045         ESTIMATE_END(id);
2046         if (ret < 0) {
2047                 return ret;
2048         }
2049
2050         if (ret & WIDGET_NEED_TO_SCHEDULE) {
2051                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2052                 (void)append_pending_list(item);
2053         }
2054
2055         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2056                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2057                 (void)append_force_update_list(item);
2058         }
2059
2060         if (ret & WIDGET_OUTPUT_UPDATED) {
2061                 update_monitor_cnt(item);
2062         }
2063
2064         return WIDGET_ERROR_NONE;
2065 }
2066
2067 HAPI int widget_viewer_is_pinned_up(const char *pkgname, const char *id)
2068 {
2069         Eina_List *l;
2070         struct instance *inst;
2071         struct item *item;
2072
2073         inst = so_find_instance(pkgname, id);
2074         if (!inst) {
2075                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2076                 return WIDGET_ERROR_INVALID_PARAMETER;
2077         }
2078
2079         l = find_item(inst);
2080         if (!l) {
2081                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2082                 return WIDGET_ERROR_NOT_EXIST;
2083         }
2084
2085         item = eina_list_data_get(l);
2086         if (!item) {
2087                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
2088                 return WIDGET_ERROR_FAULT;
2089         }
2090         /*!
2091          * NOTE:
2092          * item is not used.
2093          * Maybe this is not neccessary for this operation
2094          */
2095         return so_is_pinned_up(inst);
2096 }
2097
2098 HAPI int widget_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
2099 {
2100         Eina_List *l;
2101         struct instance *inst;
2102         struct item *item;
2103         int ret;
2104
2105         inst = so_find_instance(pkgname, id);
2106         if (!inst) {
2107                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2108                 return WIDGET_ERROR_INVALID_PARAMETER;
2109         }
2110
2111         l = find_item(inst);
2112         if (!l) {
2113                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2114                 return WIDGET_ERROR_NOT_EXIST;
2115         }
2116
2117         item = eina_list_data_get(l);
2118
2119         ret = so_change_group(inst, cluster, category);
2120         if (ret < 0) {
2121                 return ret;
2122         }
2123
2124         if (ret & WIDGET_NEED_TO_SCHEDULE) {
2125                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2126                 (void)append_pending_list(item);
2127         }
2128
2129         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2130                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2131                 (void)append_force_update_list(item);
2132         }
2133
2134         if (ret & WIDGET_OUTPUT_UPDATED) {
2135                 update_monitor_cnt(item);
2136         }
2137
2138         return WIDGET_ERROR_NONE;
2139 }
2140
2141 static int widget_sys_event(struct instance *inst, struct item *item, int event)
2142 {
2143         int ret;
2144
2145         ret = so_sys_event(inst, event);
2146         if (ret < 0) {
2147                 return ret;
2148         }
2149
2150         if (ret & WIDGET_NEED_TO_SCHEDULE) {
2151                 (void)append_pending_list(item);
2152         }
2153
2154         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2155                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
2156                 (void)append_force_update_list(item);
2157         }
2158
2159         if (ret & WIDGET_OUTPUT_UPDATED) {
2160                 update_monitor_cnt(item);
2161         }
2162
2163         return WIDGET_ERROR_NONE;
2164 }
2165
2166 HAPI int widget_system_event(const char *pkgname, const char *id, int event)
2167 {
2168         Eina_List *l;
2169         struct instance *inst;
2170         struct item *item;
2171
2172         inst = so_find_instance(pkgname, id);
2173         if (!inst) {
2174                 ErrPrint("instance %s - %s is not created\n", pkgname, id);
2175                 return WIDGET_ERROR_INVALID_PARAMETER;
2176         }
2177
2178         l = find_item(inst);
2179         if (!l) {
2180                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2181                 return WIDGET_ERROR_NOT_EXIST;
2182         }
2183
2184         item = eina_list_data_get(l);
2185         return widget_sys_event(inst, item, event);
2186 }
2187
2188 HAPI int widget_update(const char *pkgname, const char *id, int force)
2189 {
2190         Eina_List *l;
2191         struct instance *inst;
2192         struct item *item;
2193
2194         inst = so_find_instance(pkgname, id);
2195         if (!inst) {
2196                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2197                 return WIDGET_ERROR_INVALID_PARAMETER;
2198         }
2199
2200         l = find_item(inst);
2201         if (!l) {
2202                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2203                 return WIDGET_ERROR_NOT_EXIST;
2204         }
2205
2206         item = eina_list_data_get(l);
2207         if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2208                 (void)append_force_update_list(item);
2209         } else {
2210                 (void)append_pending_list(item);
2211         }
2212
2213         return WIDGET_ERROR_NONE;
2214 }
2215
2216 HAPI int widget_set_content_info(const char *pkgname, const char *id, const char *content_info)
2217 {
2218         Eina_List *l;
2219         struct instance *inst;
2220         struct item *item;
2221         int ret;
2222
2223         inst = so_find_instance(pkgname, id);
2224         if (!inst) {
2225                 ErrPrint("Instance %s - %s is not created (%s)\n", pkgname, id, content_info);
2226                 return WIDGET_ERROR_INVALID_PARAMETER;
2227         }
2228
2229         l = find_item(inst);
2230         if (!l) {
2231                 ErrPrint("Instance is not found (%s - %s, %s)\n", pkgname, id, content_info);
2232                 return WIDGET_ERROR_NOT_EXIST;
2233         }
2234
2235         item = eina_list_data_get(l);
2236         ESTIMATE_START(id);
2237         ret = so_set_content_info(inst, content_info);
2238         ESTIMATE_END(id);
2239         if (ret < 0) {
2240                 return ret;
2241         }
2242
2243         if (ret & WIDGET_NEED_TO_SCHEDULE) {
2244                 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2245                 (void)append_pending_list(item);
2246         }
2247
2248         if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2249                 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2250                 (void)append_force_update_list(item);
2251         }
2252
2253         if (ret & WIDGET_OUTPUT_UPDATED) {
2254                 update_monitor_cnt(item);
2255         }
2256
2257         return WIDGET_ERROR_NONE;
2258 }
2259
2260 HAPI int widget_update_all(const char *pkgname, const char *cluster, const char *category, int force)
2261 {
2262         Eina_List *l;
2263         Eina_List *n;
2264         struct item *item;
2265
2266         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
2267         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2268                 if (item->deleteme) {
2269                         continue;
2270                 }
2271
2272                 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
2273                         continue;
2274                 }
2275
2276                 if (category && strcasecmp(item->inst->category, category)) {
2277                         continue;
2278                 }
2279
2280                 if (pkgname && strlen(pkgname)) {
2281                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
2282                                 if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2283                                         (void)append_force_update_list(item);
2284                                 } else {
2285                                         (void)append_pending_list(item);
2286                                 }
2287                         }
2288                 } else {
2289                         if (force) {
2290                                 DbgPrint("Update All function doesn't support force update to all widgetes\n");
2291                         } else {
2292                                 (void)append_pending_list(item);
2293                         }
2294                 }
2295         }
2296
2297         return WIDGET_ERROR_NONE;
2298 }
2299
2300 HAPI int widget_set_content_info_all(const char *pkgname, const char *content)
2301 {
2302         Eina_List *l;
2303         Eina_List *n;
2304         struct item *item;
2305         register int cnt = 0;
2306
2307         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2308                 if (item->deleteme) {
2309                         continue;
2310                 }
2311
2312                 if (pkgname && strlen(pkgname)) {
2313                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
2314                                 widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2315                                 cnt++;
2316                         }
2317                 } else {
2318                         widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2319                         cnt++;
2320                 }
2321         }
2322         DbgPrint("Update content for %s - %d\n", pkgname ? pkgname : "(all)", cnt);
2323
2324         return WIDGET_ERROR_NONE;
2325 }
2326
2327 HAPI int widget_delete_all_deleteme(void)
2328 {
2329         Eina_List *l;
2330         Eina_List *n;
2331         struct item *item;
2332         int cnt = 0;
2333
2334         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2335                 if (!item->deleteme) {
2336                         continue;
2337                 }
2338
2339                 update_monitor_del(item->inst->id, item);
2340                 (void)so_destroy(item->inst, item->unload_so);
2341                 free(item);
2342                 cnt++;
2343         }
2344
2345         DbgPrint("Delete all deleteme: %d\n", cnt);
2346         return WIDGET_ERROR_NONE;
2347 }
2348
2349 HAPI int widget_delete_all(void)
2350 {
2351         Eina_List *l;
2352         Eina_List *n;
2353         struct item *item;
2354         int cnt = 0;
2355
2356         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2357                 update_monitor_del(item->inst->id, item);
2358                 (void)so_destroy(item->inst, item->unload_so);
2359                 free(item);
2360                 cnt++;
2361         }
2362
2363         DbgPrint("Delete all deleteme: %d\n", cnt);
2364         return WIDGET_ERROR_NONE;
2365 }
2366
2367 HAPI int widget_system_event_all(int event)
2368 {
2369         Eina_List *l;
2370         Eina_List *n;
2371         struct item *item;
2372
2373         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2374                 if (item->deleteme) {
2375                         continue;
2376                 }
2377
2378                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
2379                 widget_sys_event(item->inst, item, event);
2380         }
2381
2382         return WIDGET_ERROR_NONE;
2383 }
2384
2385 HAPI void widget_pause_all(void)
2386 {
2387         Eina_List *l;
2388         struct item *item;
2389
2390         if (s_info.state == STATE_PAUSED) {
2391                 return;
2392         }
2393
2394         s_info.state = STATE_PAUSED;
2395
2396         pending_timer_freeze();
2397         /*!
2398          * \note
2399          * force timer will not be freezed
2400          */
2401
2402         EINA_LIST_FOREACH(s_info.item_list, l, item) {
2403                 if (item->deleteme) {
2404                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
2405                         continue;
2406                 }
2407
2408                 if (item->state != STATE_RESUMED) {
2409                         continue;
2410                 }
2411
2412                 timer_freeze(item);
2413
2414                 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_PAUSED);
2415         }
2416 }
2417
2418 HAPI void widget_resume_all(void)
2419 {
2420         Eina_List *l;
2421         Eina_List *n;
2422         struct item *item;
2423
2424         if (s_info.state == STATE_RESUMED) {
2425                 return;
2426         }
2427
2428         s_info.state = STATE_RESUMED;
2429
2430         pending_timer_thaw();
2431
2432         /*!
2433          * \note
2434          * force timer will not affected by this
2435          */
2436
2437         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2438                 if (item->deleteme) {
2439                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
2440                         continue;
2441                 }
2442
2443                 if (item->state != STATE_RESUMED) {
2444                         continue;
2445                 }
2446
2447                 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_RESUMED);
2448
2449                 if (item->updated_in_pause) {
2450                         (void)append_pending_list(item);
2451                         item->updated_in_pause = 0;
2452                 }
2453
2454                 /*!
2455                  * \note
2456                  * After send the resume callback, call this function.
2457                  * Because the timer_thaw can call the update function.
2458                  * Before resumed event is notified to the widget,
2459                  * Do not call update function
2460                  */
2461                 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
2462                         /* item is deleted */
2463                 }
2464         }
2465 }
2466
2467 HAPI int widget_pause(const char *pkgname, const char *id)
2468 {
2469         struct instance *inst;
2470         Eina_List *l;
2471         struct item *item;
2472
2473         inst = so_find_instance(pkgname, id);
2474         if (!inst) {
2475                 return WIDGET_ERROR_INVALID_PARAMETER;
2476         }
2477
2478         l = find_item(inst);
2479         if (!l) {
2480                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2481                 return WIDGET_ERROR_NOT_EXIST;
2482         }
2483
2484         item = eina_list_data_get(l);
2485         if (!item) {
2486                 return WIDGET_ERROR_FAULT;
2487         }
2488
2489         if (item->deleteme) {
2490                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2491                 return WIDGET_ERROR_RESOURCE_BUSY;
2492         }
2493
2494         if (item->state == STATE_PAUSED) {
2495                 return WIDGET_ERROR_NONE;
2496         }
2497
2498         item->state = STATE_PAUSED;
2499
2500         if (s_info.state != STATE_RESUMED) {
2501                 return WIDGET_ERROR_NONE;
2502         }
2503
2504         timer_freeze(item);
2505
2506         widget_sys_event(inst, item, WIDGET_SYS_EVENT_PAUSED);
2507
2508         return WIDGET_ERROR_NONE;
2509 }
2510
2511 HAPI int widget_viewer_connected(const char *pkgname, const char *id, const char *direct_addr)
2512 {
2513         struct instance *inst;
2514         Eina_List *l;
2515         struct connection *conn_handle;
2516         struct item *item;
2517
2518         inst = so_find_instance(pkgname, id);
2519         if (!inst) {
2520                 return WIDGET_ERROR_INVALID_PARAMETER;
2521         }
2522
2523         l = find_item(inst);
2524         if (!l) {
2525                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2526                 return WIDGET_ERROR_NOT_EXIST;
2527         }
2528
2529         item = eina_list_data_get(l);
2530         if (!item) {
2531                 return WIDGET_ERROR_FAULT;
2532         }
2533
2534         conn_handle = connection_find_by_addr(direct_addr);
2535         if (!conn_handle) {
2536                 conn_handle = connection_create(direct_addr, (void *)s_table);
2537                 if (!conn_handle) {
2538                         ErrPrint("Direct update-path is not supported\n");
2539                 } else {
2540                         DbgPrint("Direct update-path is created: %s\n", id);
2541                         item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2542                 }
2543         } else {
2544                 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2545                 (void)connection_ref(conn_handle);
2546         }
2547
2548         return WIDGET_ERROR_NONE;
2549 }
2550
2551 HAPI int widget_viewer_disconnected(const char *pkgname, const char *id, const char *direct_addr)
2552 {
2553         struct instance *inst;
2554         Eina_List *l;
2555         struct item *item;
2556         struct connection *conn_handle;
2557
2558         inst = so_find_instance(pkgname, id);
2559         if (!inst) {
2560                 return WIDGET_ERROR_INVALID_PARAMETER;
2561         }
2562
2563         l = find_item(inst);
2564         if (!l) {
2565                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2566                 return WIDGET_ERROR_NOT_EXIST;
2567         }
2568
2569         item = eina_list_data_get(l);
2570         if (!item) {
2571                 return WIDGET_ERROR_FAULT;
2572         }
2573
2574         conn_handle = connection_find_by_addr(direct_addr);
2575         if (conn_handle) {
2576                 if (eina_list_data_find(item->direct_path_list, conn_handle)) {
2577                         item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
2578                         connection_unref(conn_handle);
2579                 }
2580         }
2581
2582         return WIDGET_ERROR_NONE;
2583 }
2584
2585 HAPI int widget_resume(const char *pkgname, const char *id)
2586 {
2587         struct instance *inst;
2588         Eina_List *l;
2589         struct item *item;
2590         int ret;
2591
2592         inst = so_find_instance(pkgname, id);
2593         if (!inst) {
2594                 return WIDGET_ERROR_INVALID_PARAMETER;
2595         }
2596
2597         l = find_item(inst);
2598         if (!l) {
2599                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2600                 return WIDGET_ERROR_NOT_EXIST;
2601         }
2602
2603         item = eina_list_data_get(l);
2604         if (!item) {
2605                 return WIDGET_ERROR_FAULT;
2606         }
2607
2608         if (item->deleteme) {
2609                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2610                 return WIDGET_ERROR_RESOURCE_BUSY;
2611         }
2612
2613         if (item->state == STATE_RESUMED) {
2614                 return WIDGET_ERROR_NONE;
2615         }
2616
2617         item->state = STATE_RESUMED;
2618
2619         if (s_info.state != STATE_RESUMED) {
2620                 return WIDGET_ERROR_NONE;
2621         }
2622
2623         widget_sys_event(inst, item, WIDGET_SYS_EVENT_RESUMED);
2624
2625         ret = timer_thaw(item);
2626         if (ret == UPDATE_ITEM_DELETED) {
2627                 /*!
2628                  * \note
2629                  * ITEM is deleted
2630                  */
2631                 return WIDGET_ERROR_NONE;
2632         } else if (ret == UPDATE_INVOKED) {
2633                 /*!
2634                  * \note
2635                  * if the update is successfully done, the updated_in_pause will be reset'd.
2636                  * or append it to the pending list
2637                  */
2638         }
2639
2640         if (item->updated_in_pause) {
2641                 (void)append_pending_list(item);
2642                 item->updated_in_pause = 0;
2643         }
2644
2645         return WIDGET_ERROR_NONE;
2646 }
2647
2648 HAPI void widget_turn_secured_on(void)
2649 {
2650         s_info.secured = 1;
2651 }
2652
2653 HAPI int widget_is_secured(void)
2654 {
2655         return s_info.secured;
2656 }
2657
2658 HAPI int widget_is_all_paused(void)
2659 {
2660         return s_info.state != STATE_RESUMED;
2661 }
2662
2663 HAPI int widget_set_orientation(const char *pkgname, const char *id, int orientation)
2664 {
2665         Eina_List *l;
2666         struct instance *inst;
2667         struct item *item;
2668
2669         inst = so_find_instance(pkgname, id);
2670         if (!inst) {
2671                 ErrPrint("instance %s - %s is not created\n", pkgname, id);
2672                 return WIDGET_ERROR_INVALID_PARAMETER;
2673         }
2674
2675         l = find_item(inst);
2676         if (!l) {
2677                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2678                 return WIDGET_ERROR_NOT_EXIST;
2679         }
2680
2681         inst->orientation = orientation;
2682
2683         item = eina_list_data_get(l);
2684         return widget_sys_event(inst, item, WIDGET_SYS_EVENT_ORIENTATION_CHANGED);
2685 }
2686
2687 int widget_provider_app_get_orientation(const char *filename)
2688 {
2689         Eina_List *l;
2690         struct item *item;
2691
2692         EINA_LIST_FOREACH(s_info.item_list, l, item) {
2693                 if (!strcmp(widget_util_uri_to_path(item->inst->id), filename)) {
2694                         return item->inst->orientation;
2695                 }
2696         }
2697
2698         return WIDGET_ERROR_NOT_EXIST;
2699 }
2700
2701 /* End of a file */