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