55709cba12863df8b13f3df60af37f7cc96ab220
[platform/core/appfw/data-provider-slave.git] / src / so_handler.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 <errno.h>
19 #include <dlfcn.h> /* dlopen */
20 #include <stdlib.h> /* malloc, free */
21 #include <string.h> /* strcmp */
22
23 #include <dlog.h>
24 #include <Eina.h>
25 #include <widget_errno.h>
26 #include <widget_provider.h>
27 #include <widget_service.h>
28 #include <widget_service_internal.h>
29 #include <widget_script.h>
30 #include <widget_conf.h>
31
32 #include "main.h"
33 #include "critical_log.h"
34 #include "debug.h"
35 #include "so_handler.h"
36 #include "fault.h"
37 #include "util.h"
38 #include "conf.h"
39
40 int errno;
41
42 static struct info {
43         Eina_List *widget_list;
44         enum current_operations current_op;
45 } s_info = {
46         .widget_list = NULL,
47         .current_op = WIDGET_OP_UNKNOWN,
48 };
49
50 static inline struct so_item *find_widget(const char *pkgname)
51 {
52         Eina_List *l;
53         struct so_item *item;
54
55         EINA_LIST_FOREACH(s_info.widget_list, l, item) {
56                 if (!strcmp(item->pkgname, pkgname)) {
57                         return item;
58                 }
59         }
60
61         return NULL;
62 }
63
64 static inline char *so_adaptor_alloc(const char *abi)
65 {
66         /* TODO: Implement me */
67         DbgPrint("ABI[%s] loads %s\n", abi, "/usr/lib/libwidget-cpp.so");
68         return strdup("/usr/lib/libwidget-cpp.so");
69 }
70
71 static inline char *so_path_alloc(const char *pkgname)
72 {
73         char *widget_id;
74         char *path;
75
76         widget_id = widget_service_get_widget_id(pkgname);
77         if (!widget_id) {
78                 ErrPrint("Failed to get package name\n");
79                 return NULL;
80         } else {
81                 path = widget_service_get_libexec(widget_id);
82                 free(widget_id);
83         }
84
85         DbgPrint("so path: %s\n", path);
86         return path;
87 }
88
89 static void delete_widget(struct so_item *item)
90 {
91         int ret;
92
93         fault_mark_call(item->pkgname, "finalize", __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
94
95         if (item->adaptor.finalize) {
96                 ret = item->adaptor.finalize(item->pkgname);
97         } else if (item->widget.finalize) {
98                 ret = item->widget.finalize();
99         } else {
100                 ErrPrint("%s has no finalize\n", item->pkgname);
101                 ret = WIDGET_ERROR_NOT_SUPPORTED;
102         }
103
104         fault_unmark_call(item->pkgname, "finalize", __func__, USE_ALARM);
105
106         if (ret == WIDGET_ERROR_RESOURCE_BUSY) {
107                 DbgPrint("Keep SO in a process space (%s)\n", item->so_fname);
108         } else {
109                 if (ret < 0) {
110                         ErrPrint("Package %s, finalize returns %d\n", item->pkgname, ret);
111                 }
112                 DbgPrint("Unload SO from process space (%s)\n", item->so_fname);
113                 s_info.widget_list = eina_list_remove(s_info.widget_list, item);
114                 main_heap_monitor_del_target(item->so_fname);
115                 util_dump_current_so_info(item->so_fname);
116                 if (dlclose(item->handle) != 0) {
117                         ErrPrint("dlclose: %s\n", dlerror());
118                 }
119                 free(item->so_fname);
120                 free(item->pkgname);
121                 free(item);
122         }
123 }
124
125 static struct so_item *new_adaptor(const char *pkgname, const char *abi)
126 {
127         struct so_item *item;
128         char *errmsg;
129
130         item = calloc(1, sizeof(*item));
131         if (!item) {
132                 ErrPrint("calloc: %d\n", errno);
133                 return NULL;
134         }
135
136         item->pkgname = strdup(pkgname);
137         if (!item->pkgname) {
138                 ErrPrint("strdup: %d\n", errno);
139                 free(item);
140                 return NULL;
141         }
142
143         /*! \TODO:
144          * item->timeout
145          */
146
147         /*! \TODO
148          * item->has_widget_script
149          */
150
151         item->inst_list = NULL;
152
153         item->so_fname = so_adaptor_alloc(abi);
154         if (!item->so_fname) {
155                 free(item->pkgname);
156                 free(item);
157                 return NULL;
158         }
159
160         fault_mark_call(pkgname, __func__, __func__, USE_ALARM, DEFAULT_LOAD_TIMER);
161         item->handle = dlopen(item->so_fname, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
162         if (!item->handle) {
163                 fault_unmark_call(pkgname, __func__, __func__, USE_ALARM);
164                 ErrPrint("dlopen: %s - %s\n", dlerror(), item->so_fname);
165                 free(item->so_fname);
166                 free(item->pkgname);
167                 free(item);
168                 return NULL;
169         }
170         fault_unmark_call(pkgname, __func__, __func__, USE_ALARM);
171
172         errmsg = dlerror();
173         if (errmsg) {
174                 DbgPrint("dlerror(can be ignored): %s\n", errmsg);
175         }
176
177         item->adaptor.create = (adaptor_create_t)dlsym(item->handle, "widget_create");
178         if (!item->adaptor.create) {
179                 ErrPrint("symbol: widget_create - %s\n", dlerror());
180                 delete_widget(item);
181                 return NULL;
182         }
183
184         item->adaptor.destroy = (adaptor_destroy_t)dlsym(item->handle, "widget_destroy");
185         if (!item->adaptor.destroy) {
186                 ErrPrint("symbol: widget_destroy - %s\n", dlerror());
187                 delete_widget(item);
188                 return NULL;
189         }
190
191         item->adaptor.pinup = (adaptor_pinup_t)dlsym(item->handle, "widget_pinup");
192         if (!item->adaptor.pinup) {
193                 ErrPrint("symbol: widget_pinup - %s\n", dlerror());
194         }
195
196         item->adaptor.is_updated = (adaptor_is_updated_t)dlsym(item->handle, "widget_need_to_update");
197         if (!item->adaptor.is_updated) {
198                 ErrPrint("symbol: widget_need_to_update - %s\n", dlerror());
199         }
200
201         item->adaptor.update_content = (adaptor_update_content_t)dlsym(item->handle, "widget_update_content");
202         if (!item->adaptor.update_content) {
203                 ErrPrint("symbol: widget_update_content - %s\n", dlerror());
204         }
205
206         item->adaptor.clicked = (adaptor_clicked_t)dlsym(item->handle, "widget_clicked");
207         if (!item->adaptor.clicked) {
208                 ErrPrint("symbol: widget_clicked - %s\n", dlerror());
209         }
210
211         item->adaptor.text_signal = (adaptor_text_signal_t)dlsym(item->handle, "widget_content_event");
212         if (!item->adaptor.text_signal) {
213                 ErrPrint("symbol: widget_content_event - %s\n", dlerror());
214         }
215
216         item->adaptor.resize = (adaptor_resize_t)dlsym(item->handle, "widget_resize");
217         if (!item->adaptor.resize) {
218                 ErrPrint("symbol: widget_resize - %s\n", dlerror());
219         }
220
221         item->adaptor.create_needed = (adaptor_create_needed_t)dlsym(item->handle, "widget_need_to_create");
222         if (!item->adaptor.create_needed) {
223                 ErrPrint("symbol: widget_need_to_create - %s\n", dlerror());
224         }
225
226         item->adaptor.change_group = (adaptor_change_group_t)dlsym(item->handle, "widget_change_group");
227         if (!item->adaptor.change_group) {
228                 ErrPrint("symbol: widget_change_group - %s\n", dlerror());
229         }
230
231         item->adaptor.get_output_info = (adaptor_get_output_info_t)dlsym(item->handle, "widget_get_info");
232         if (!item->adaptor.get_output_info) {
233                 ErrPrint("symbol: widget_get_info - %s\n", dlerror());
234         }
235
236         item->adaptor.initialize = (adaptor_initialize_t)dlsym(item->handle, "widget_initialize");
237         if (!item->adaptor.initialize) {
238                 ErrPrint("symbol: widget_initialize - %s\n", dlerror());
239         }
240
241         item->adaptor.finalize = (adaptor_finalize_t)dlsym(item->handle, "widget_finalize");
242         if (!item->adaptor.finalize) {
243                 ErrPrint("symbol: widget_finalize - %s\n", dlerror());
244         }
245
246         item->adaptor.need_to_destroy = (adaptor_need_to_destroy_t)dlsym(item->handle, "widget_need_to_destroy");
247         if (!item->adaptor.need_to_destroy) {
248                 ErrPrint("symbol: widget_need_to_destroy - %s\n", dlerror());
249         }
250
251         item->adaptor.sys_event = (adaptor_system_event_t)dlsym(item->handle, "widget_system_event");
252         if (!item->adaptor.sys_event) {
253                 ErrPrint("symbol: lievbox_system_event - %s\n", dlerror());
254         }
255
256         item->adaptor.is_pinned_up = (adaptor_is_pinned_up_t)dlsym(item->handle, "widget_is_pinned_up");
257         if (!item->adaptor.is_pinned_up) {
258                 ErrPrint("symbol: widget_is_pinned_up - %s\n", dlerror());
259         }
260
261         item->adaptor.get_alt_info = (adaptor_get_alt_info_t)dlsym(item->handle, "widget_get_alt_info");
262         if (!item->adaptor.get_alt_info) {
263                 ErrPrint("symbol: widget_get_alt_info - %s\n", dlerror());
264         }
265
266         item->adaptor.set_content_info = (adaptor_set_content_info_t)dlsym(item->handle, "widget_set_content_info");
267         if (!item->adaptor.set_content_info) {
268                 ErrPrint("symbol: widget_set_content_info - %s\n", dlerror());
269         }
270
271         if (item->adaptor.initialize) {
272                 int ret;
273                 fault_mark_call(pkgname, "initialize", __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
274
275                 ret = item->adaptor.initialize(pkgname);
276
277                 fault_unmark_call(pkgname, "initialize", __func__, USE_ALARM);
278                 if (ret < 0) {
279                         ErrPrint("Failed to initialize package %s\n", pkgname);
280                         delete_widget(item);
281                         return NULL;
282                 }
283         }
284
285         s_info.widget_list = eina_list_append(s_info.widget_list, item);
286         return item;
287 }
288
289 static struct so_item *new_widget(const char *pkgname)
290 {
291         struct so_item *item;
292         char *errmsg;
293
294         item = calloc(1, sizeof(*item));
295         if (!item) {
296                 ErrPrint("calloc: %d\n", errno);
297                 return NULL;
298         }
299
300         item->pkgname = strdup(pkgname);
301         if (!item->pkgname) {
302                 ErrPrint("strdup: %d\n", errno);
303                 free(item);
304                 return NULL;
305         }
306
307         /*! \TODO:
308          * item->timeout
309          */
310
311         /*! \TODO
312          * item->has_widget_script
313          */
314
315         item->inst_list = NULL;
316
317         item->so_fname = so_path_alloc(pkgname);
318         if (!item->so_fname) {
319                 free(item->pkgname);
320                 free(item);
321                 return NULL;
322         }
323
324         fault_mark_call(pkgname, __func__, __func__, USE_ALARM, DEFAULT_LOAD_TIMER);
325         item->handle = dlopen(item->so_fname, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
326         if (!item->handle) {
327                 fault_unmark_call(pkgname, __func__, __func__, USE_ALARM);
328                 ErrPrint("dlopen: %s - %s\n", dlerror(), item->so_fname);
329                 free(item->so_fname);
330                 free(item->pkgname);
331                 free(item);
332                 return NULL;
333         }
334         fault_unmark_call(pkgname, __func__, __func__, USE_ALARM);
335
336         errmsg = dlerror();
337         if (errmsg) {
338                 DbgPrint("dlerror(can be ignored): %s\n", errmsg);
339         }
340
341         item->widget.create = (create_t)dlsym(item->handle, "widget_create");
342         if (!item->widget.create) {
343                 ErrPrint("symbol: widget_create - %s\n", dlerror());
344                 delete_widget(item);
345                 return NULL;
346         }
347
348         item->widget.destroy = (destroy_t)dlsym(item->handle, "widget_destroy");
349         if (!item->widget.destroy) {
350                 ErrPrint("symbol: widget_destroy - %s\n", dlerror());
351                 delete_widget(item);
352                 return NULL;
353         }
354
355         item->widget.pinup = (pinup_t)dlsym(item->handle, "widget_pinup");
356         if (!item->widget.pinup) {
357                 ErrPrint("symbol: widget_pinup - %s\n", dlerror());
358         }
359
360         item->widget.is_updated = (is_updated_t)dlsym(item->handle, "widget_need_to_update");
361         if (!item->widget.is_updated) {
362                 ErrPrint("symbol: widget_need_to_update - %s\n", dlerror());
363         }
364
365         item->widget.update_content = (update_content_t)dlsym(item->handle, "widget_update_content");
366         if (!item->widget.update_content) {
367                 ErrPrint("symbol: widget_update_content - %s\n", dlerror());
368         }
369
370         item->widget.clicked = (clicked_t)dlsym(item->handle, "widget_clicked");
371         if (!item->widget.clicked) {
372                 ErrPrint("symbol: widget_clicked - %s\n", dlerror());
373         }
374
375         item->widget.text_signal = (text_signal_t)dlsym(item->handle, "widget_content_event");
376         if (!item->widget.text_signal) {
377                 ErrPrint("symbol: widget_content_event - %s\n", dlerror());
378         }
379
380         item->widget.resize = (resize_t)dlsym(item->handle, "widget_resize");
381         if (!item->widget.resize) {
382                 ErrPrint("symbol: widget_resize - %s\n", dlerror());
383         }
384
385         item->widget.create_needed = (create_needed_t)dlsym(item->handle, "widget_need_to_create");
386         if (!item->widget.create_needed) {
387                 ErrPrint("symbol: widget_need_to_create - %s\n", dlerror());
388         }
389
390         item->widget.change_group = (change_group_t)dlsym(item->handle, "widget_change_group");
391         if (!item->widget.change_group) {
392                 ErrPrint("symbol: widget_change_group - %s\n", dlerror());
393         }
394
395         item->widget.get_output_info = (get_output_info_t)dlsym(item->handle, "widget_get_info");
396         if (!item->widget.get_output_info) {
397                 ErrPrint("symbol: widget_get_info - %s\n", dlerror());
398         }
399
400         item->widget.initialize = (initialize_t)dlsym(item->handle, "widget_initialize");
401         if (!item->widget.initialize) {
402                 ErrPrint("symbol: widget_initialize - %s\n", dlerror());
403         }
404
405         item->widget.finalize = (finalize_t)dlsym(item->handle, "widget_finalize");
406         if (!item->widget.finalize) {
407                 ErrPrint("symbol: widget_finalize - %s\n", dlerror());
408         }
409
410         item->widget.need_to_destroy = (need_to_destroy_t)dlsym(item->handle, "widget_need_to_destroy");
411         if (!item->widget.need_to_destroy) {
412                 ErrPrint("symbol: widget_need_to_destroy - %s\n", dlerror());
413         }
414
415         item->widget.sys_event = (system_event_t)dlsym(item->handle, "widget_system_event");
416         if (!item->widget.sys_event) {
417                 ErrPrint("symbol: widget_system_event - %s\n", dlerror());
418         }
419
420         item->widget.is_pinned_up = (is_pinned_up_t)dlsym(item->handle, "widget_is_pinned_up");
421         if (!item->widget.is_pinned_up) {
422                 ErrPrint("symbol: widget_is_pinned_up - %s\n", dlerror());
423         }
424
425         item->widget.get_alt_info = (get_alt_info_t)dlsym(item->handle, "widget_get_alt_info");
426         if (!item->widget.get_alt_info) {
427                 ErrPrint("symbol: widget_get_alt_info - %s\n", dlerror());
428         }
429
430         item->widget.set_content_info = (set_content_info_t)dlsym(item->handle, "widget_set_content_info");
431         if (!item->widget.set_content_info) {
432                 ErrPrint("symbol: widget_set_content_info - %s\n", dlerror());
433         }
434
435         main_heap_monitor_add_target(item->so_fname);
436
437         if (item->widget.initialize) {
438                 int ret;
439                 fault_mark_call(pkgname, "initialize", __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
440
441                 ret = item->widget.initialize(pkgname);
442
443                 fault_unmark_call(pkgname, "initialize", __func__, USE_ALARM);
444                 if (ret < 0) {
445                         ErrPrint("Failed to initialize package %s\n", pkgname);
446                         delete_widget(item);
447                         return NULL;
448                 }
449         }
450
451         s_info.widget_list = eina_list_append(s_info.widget_list, item);
452         return item;
453 }
454
455 static inline struct instance *new_instance(const char *id, const char *content, const char *cluster, const char *category)
456 {
457         struct instance *inst;
458
459         inst = calloc(1, sizeof(*inst));
460         if (!inst) {
461                 ErrPrint("calloc: %d\n", errno);
462                 return NULL;
463         }
464
465         inst->id = strdup(id);
466         if (!inst->id) {
467                 ErrPrint("strdup: %d\n", errno);
468                 free(inst);
469                 return NULL;
470         }
471
472         DbgPrint("Default content: [%s]\n", content);
473         if (content) {
474                 inst->content = strdup(content);
475                 if (!inst->content) {
476                         ErrPrint("strdup: %d\n", errno);
477                         free(inst->id);
478                         free(inst);
479                         return NULL;
480                 }
481         }
482
483         if (cluster) {
484                 inst->cluster = strdup(cluster);
485                 if (!inst->cluster) {
486                         ErrPrint("strdup: %d\n", errno);
487                         free(inst->id);
488                         free(inst->content);
489                         free(inst);
490                         return NULL;
491                 }
492         }
493
494         if (category) {
495                 inst->category = strdup(category);
496                 if (!inst->category) {
497                         ErrPrint("strdup: %d\n", errno);
498                         free(inst->cluster);
499                         free(inst->id);
500                         free(inst->content);
501                         free(inst);
502                         return NULL;
503                 }
504         }
505
506         return inst;
507 }
508
509 static inline int delete_instance(struct instance *inst)
510 {
511         free(inst->icon);
512         free(inst->name);
513         free(inst->cluster);
514         free(inst->category);
515         free(inst->id);
516         free(inst->content);
517         free(inst->title);
518         free(inst);
519         return WIDGET_ERROR_NONE;
520 }
521
522 static inline struct instance *find_instance(struct so_item *item, const char *id)
523 {
524         struct instance *inst;
525         Eina_List *l;
526
527         EINA_LIST_FOREACH(item->inst_list, l, inst) {
528                 if (!strcmp(inst->id, id)) {
529                         return inst;
530                 }
531         }
532
533         return NULL;
534 }
535
536 HAPI struct instance *so_find_instance(const char *pkgname, const char *id)
537 {
538         struct so_item *item;
539
540         item = find_widget(pkgname);
541         if (!item) {
542                 return NULL;
543         }
544
545         return find_instance(item, id);
546 }
547
548 HAPI int so_create(const char *pkgname, const char *id, const char *content_info, int timeout, int has_widget_script, const char *cluster, const char *category, const char *abi, struct instance **out)
549 {
550         struct so_item *item;
551         struct instance *inst;
552         int ret;
553
554         item = find_widget(pkgname);
555         if (item) {
556                 inst = find_instance(item, id);
557                 if (inst) {
558                         ErrPrint("Instance: %s - %s is already exists\n", pkgname, id);
559                         return WIDGET_ERROR_ALREADY_EXIST;
560                 }
561         } else {
562                 if (!strcasecmp(abi, "c")) {
563                         item = new_widget(pkgname);
564                 } else {
565                         item = new_adaptor(pkgname, abi);
566                 }
567
568                 if (!item) {
569                         return WIDGET_ERROR_FAULT;
570                 }
571         }
572
573         inst = new_instance(id, content_info, cluster, category);
574         if (!inst) {
575                 if (!item->inst_list) {
576                         delete_widget(item);
577                 }
578
579                 return WIDGET_ERROR_FAULT;
580         }
581
582         item->inst_list = eina_list_append(item->inst_list, inst);
583         item->has_widget_script = has_widget_script;
584         item->timeout = timeout;
585
586         fault_mark_call(pkgname, id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
587
588         s_info.current_op = WIDGET_OP_CREATE;
589         if (item->adaptor.create) {
590                 ret = item->adaptor.create(pkgname, util_uri_to_path(id), content_info, cluster, category);
591         } else if (item->widget.create) {
592                 ret = item->widget.create(util_uri_to_path(id), content_info, cluster, category);
593         } else { /*! \NOTE: This is not possible, but for the exceptional handling */
594                 ret = WIDGET_ERROR_NOT_SUPPORTED;
595         }
596         s_info.current_op = WIDGET_OP_UNKNOWN;
597
598         fault_unmark_call(pkgname, id, __func__, USE_ALARM);
599
600         if (ret < 0) {
601                 item->inst_list = eina_list_remove(item->inst_list, inst);
602                 delete_instance(inst);
603
604                 if (!item->inst_list) {
605                         /* There is no instances, unload this widget */
606                         delete_widget(item);
607                 }
608                 return ret;
609         }
610
611         inst->item = item;
612         *out = inst;
613         return ret;
614 }
615
616 HAPI int so_destroy(struct instance *inst, int unload)
617 {
618         struct so_item *item;
619         int ret;
620
621         item = inst->item;
622         if (!item) {
623                 return WIDGET_ERROR_INVALID_PARAMETER;
624         }
625
626         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
627
628         s_info.current_op = WIDGET_OP_DESTROY;
629         if (item->adaptor.destroy) {
630                 ret = item->adaptor.destroy(item->pkgname, util_uri_to_path(inst->id));
631         } else if (item->widget.destroy) {
632                 ret = item->widget.destroy(util_uri_to_path(inst->id));
633         } else {
634                 ret = WIDGET_ERROR_NOT_SUPPORTED;
635         }
636         s_info.current_op = WIDGET_OP_UNKNOWN;
637
638         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
639
640         item->inst_list = eina_list_remove(item->inst_list, inst);
641         delete_instance(inst);
642
643         if (unload && !item->inst_list) {
644                 delete_widget(item);
645         }
646
647         return ret;
648 }
649
650 HAPI char *so_pinup(struct instance *inst, int pinup)
651 {
652         struct so_item *item;
653         char *ret;
654
655         item = inst->item;
656         if (!item) {
657                 return NULL;
658         }
659
660         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
661
662         s_info.current_op = WIDGET_OP_PINUP;
663         if (item->adaptor.pinup) {
664                 ret = item->adaptor.pinup(item->pkgname, util_uri_to_path(inst->id), pinup);
665         } else if (item->widget.pinup) {
666                 ret = item->widget.pinup(util_uri_to_path(inst->id), pinup);
667         } else {
668                 ret = NULL;
669         }
670         s_info.current_op = WIDGET_OP_UNKNOWN;
671
672         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
673         return ret;
674 }
675
676 HAPI int so_is_pinned_up(struct instance *inst)
677 {
678         struct so_item *item;
679         int ret;
680
681         item = inst->item;
682         if (!item) {
683                 return WIDGET_ERROR_INVALID_PARAMETER;
684         }
685
686         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
687
688         s_info.current_op = WIDGET_OP_IS_PINNED_UP;
689         if (item->adaptor.is_pinned_up) {
690                 ret = item->adaptor.is_pinned_up(item->pkgname, util_uri_to_path(inst->id));
691         } else if (item->widget.is_pinned_up) {
692                 ret = item->widget.is_pinned_up(util_uri_to_path(inst->id));
693         } else {
694                 ret = WIDGET_ERROR_NOT_SUPPORTED;
695         }
696         s_info.current_op = WIDGET_OP_UNKNOWN;
697
698         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
699         return ret;
700 }
701
702 HAPI int so_is_updated(struct instance *inst)
703 {
704         struct so_item *item;
705         int ret;
706
707         item = inst->item;
708         if (!item) {
709                 return WIDGET_ERROR_INVALID_PARAMETER;
710         }
711
712         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
713
714         s_info.current_op = WIDGET_OP_NEED_TO_UPDATE;
715         if (item->adaptor.is_updated) {
716                 ret = item->adaptor.is_updated(item->pkgname, util_uri_to_path(inst->id));
717         } else if (item->widget.is_updated) {
718                 ret = item->widget.is_updated(util_uri_to_path(inst->id));
719         } else {
720                 ret = WIDGET_ERROR_NOT_SUPPORTED;
721         }
722         s_info.current_op = WIDGET_OP_UNKNOWN;
723
724         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
725
726         return ret;
727 }
728
729 HAPI int so_need_to_destroy(struct instance *inst)
730 {
731         struct so_item *item;
732         int ret;
733
734         item = inst->item;
735         if (!item) {
736                 return WIDGET_ERROR_INVALID_PARAMETER;
737         }
738
739         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
740
741         s_info.current_op = WIDGET_OP_NEED_TO_DESTROY;
742         if (item->adaptor.need_to_destroy) {
743                 ret = item->adaptor.need_to_destroy(item->pkgname, util_uri_to_path(inst->id));
744         } else if (item->widget.need_to_destroy) {
745                 ret = item->widget.need_to_destroy(util_uri_to_path(inst->id));
746         } else {
747                 ret = WIDGET_ERROR_NOT_SUPPORTED;
748         }
749         s_info.current_op = WIDGET_OP_UNKNOWN;
750
751         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
752
753         return ret;
754 }
755
756 HAPI int so_update(struct instance *inst)
757 {
758         struct so_item *item;
759         int ret;
760
761         item = inst->item;
762         if (!item) {
763                 return WIDGET_ERROR_INVALID_PARAMETER;
764         }
765
766         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
767
768         s_info.current_op = WIDGET_OP_UPDATE_CONTENT;
769         if (item->adaptor.update_content) {
770                 ret = item->adaptor.update_content(item->pkgname, util_uri_to_path(inst->id));
771         } else if (item->widget.update_content) {
772                 ret = item->widget.update_content(util_uri_to_path(inst->id));
773         } else {
774                 ret = WIDGET_ERROR_NOT_SUPPORTED;
775         }
776         s_info.current_op = WIDGET_OP_UNKNOWN;
777
778         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
779         return ret;
780 }
781
782 HAPI int so_clicked(struct instance *inst, const char *event, double timestamp, double x, double y)
783 {
784         struct so_item *item;
785         int ret;
786
787         item = inst->item;
788         if (!item) {
789                 return WIDGET_ERROR_INVALID_PARAMETER;
790         }
791
792         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
793
794         DbgPrint("PERF_WIDGET\n");
795
796         s_info.current_op = WIDGET_OP_CLICKED;
797         if (item->adaptor.clicked) {
798                 ret = item->adaptor.clicked(item->pkgname, util_uri_to_path(inst->id), event, timestamp, x, y);
799         } else if (item->widget.clicked) {
800                 ret = item->widget.clicked(util_uri_to_path(inst->id), event, timestamp, x, y);
801         } else {
802                 ret = WIDGET_ERROR_NOT_SUPPORTED;
803         }
804         s_info.current_op = WIDGET_OP_UNKNOWN;
805
806         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
807
808         return ret;
809 }
810
811 HAPI int so_script_event(struct instance *inst, const char *signal_name, const char *source, widget_event_info_s event_info)
812 {
813         struct so_item *item;
814         int ret;
815
816         item = inst->item;
817         if (!item) {
818                 return WIDGET_ERROR_INVALID_PARAMETER;
819         }
820
821         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
822
823         s_info.current_op = WIDGET_OP_CONTENT_EVENT;
824         if (item->adaptor.text_signal) {
825                 ret = item->adaptor.text_signal(item->pkgname, util_uri_to_path(inst->id), signal_name, source, event_info);
826         } else if (item->widget.text_signal) {
827                 ret = item->widget.text_signal(util_uri_to_path(inst->id), signal_name, source, event_info);
828         } else {
829                 ret = WIDGET_ERROR_NOT_SUPPORTED;
830         }
831         s_info.current_op = WIDGET_OP_UNKNOWN;
832
833         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
834
835         return ret;
836 }
837
838 HAPI int so_resize(struct instance *inst, int w, int h)
839 {
840         struct so_item *item;
841         int ret;
842         widget_size_type_e type = WIDGET_SIZE_TYPE_UNKNOWN;
843
844         item = inst->item;
845         if (!item) {
846                 return WIDGET_ERROR_INVALID_PARAMETER;
847         }
848
849         widget_service_get_size_type(w, h, &type);
850         if (type == WIDGET_SIZE_TYPE_UNKNOWN) {
851                 return WIDGET_ERROR_INVALID_PARAMETER;
852         }
853
854         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
855
856         s_info.current_op = WIDGET_OP_RESIZE;
857         if (item->adaptor.resize) {
858                 ret = item->adaptor.resize(item->pkgname, util_uri_to_path(inst->id), type);
859         } else if (item->widget.resize) {
860                 ret = item->widget.resize(util_uri_to_path(inst->id), type);
861         } else {
862                 ret = WIDGET_ERROR_NOT_SUPPORTED;
863         }
864         s_info.current_op = WIDGET_OP_UNKNOWN;
865
866         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
867
868         return ret;
869 }
870
871 HAPI int so_set_content_info(struct instance *inst, const char *content_info)
872 {
873         struct so_item *item;
874         bundle *b;
875         int ret;
876         int len;
877
878         item = inst->item;
879         if (!item) {
880                 return WIDGET_ERROR_INVALID_PARAMETER;
881         }
882
883         if (content_info && (len = strlen(content_info))) {
884                 b = bundle_decode((const bundle_raw *)content_info, len);
885         } else {
886                 b = NULL;
887         }
888
889         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
890         s_info.current_op = WIDGET_OP_SET_CONTENT_INFO;
891         if (item->adaptor.set_content_info) {
892                 ret = item->adaptor.set_content_info(item->pkgname, util_uri_to_path(inst->id), b);
893         } else if (item->widget.set_content_info) {
894                 ret = item->widget.set_content_info(util_uri_to_path(inst->id), b);
895         } else {
896                 ret = WIDGET_ERROR_NOT_SUPPORTED;
897         }
898
899         if (b) {
900                 bundle_free(b);
901         }
902
903         s_info.current_op = WIDGET_OP_UNKNOWN;
904         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
905
906         return ret;
907 }
908
909 HAPI int so_create_needed(const char *pkgname, const char *cluster, const char *category, const char *abi)
910 {
911         struct so_item *item;
912         int ret;
913
914         item = find_widget(pkgname);
915         if (!item) {
916                 if (!strcasecmp(abi, "c")) {
917                         item = new_widget(pkgname);
918                 } else {
919                         item = new_adaptor(pkgname, abi);
920                 }
921
922                 if (!item) {
923                         return WIDGET_ERROR_FAULT;
924                 }
925         }
926
927         fault_mark_call(item->pkgname, __func__, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
928
929         s_info.current_op = WIDGET_OP_NEED_TO_CREATE;
930         if (item->adaptor.create_needed) {
931                 ret = item->adaptor.create_needed(pkgname, cluster, category);
932         } else if (item->widget.create_needed) {
933                 ret = item->widget.create_needed(cluster, category);
934         } else {
935                 ret = WIDGET_ERROR_NOT_SUPPORTED;
936         }
937         s_info.current_op = WIDGET_OP_UNKNOWN;
938
939         fault_unmark_call(item->pkgname, __func__, __func__, USE_ALARM);
940
941         DbgPrint("[%s] returns %d\n", pkgname, ret);
942         return ret;
943 }
944
945 HAPI int so_change_group(struct instance *inst, const char *cluster, const char *category)
946 {
947         struct so_item *item;
948         int ret;
949         char *tmp_cluster;
950         char *tmp_category;
951
952         item = inst->item;
953         if (!item) {
954                 return WIDGET_ERROR_INVALID_PARAMETER;
955         }
956
957         tmp_cluster = strdup(cluster);
958         if (!tmp_cluster) {
959                 return WIDGET_ERROR_OUT_OF_MEMORY;
960         }
961
962         tmp_category = strdup(category);
963         if (!tmp_category) {
964                 free(tmp_cluster);
965                 return WIDGET_ERROR_OUT_OF_MEMORY;
966         }
967
968         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
969
970         s_info.current_op = WIDGET_OP_CHANGE_GROUP;
971         if (item->adaptor.change_group) {
972                 ret = item->adaptor.change_group(item->pkgname, util_uri_to_path(inst->id), cluster, category);
973         } else if (item->widget.change_group) {
974                 ret = item->widget.change_group(util_uri_to_path(inst->id), cluster, category);
975         } else {
976                 ret = WIDGET_ERROR_NOT_SUPPORTED;
977         }
978         s_info.current_op = WIDGET_OP_UNKNOWN;
979
980         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
981         if (ret >= 0) {
982                 free(inst->cluster);
983                 free(inst->category);
984
985                 inst->cluster = tmp_cluster;
986                 inst->category = tmp_category;
987         } else {
988                 free(tmp_cluster);
989                 free(tmp_category);
990         }
991
992         return ret;
993 }
994
995 HAPI int so_get_alt_info(struct instance *inst, char **icon, char **name)
996 {
997         struct so_item *item;
998         int ret;
999
1000         item = inst->item;
1001         if (!item) {
1002                 return WIDGET_ERROR_INVALID_PARAMETER;
1003         }
1004
1005         *icon = NULL;
1006         *name = NULL;
1007
1008         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
1009
1010         s_info.current_op = WIDGET_OP_GET_ALT_INFO;
1011         if (item->adaptor.get_alt_info) {
1012                 ret = item->adaptor.get_alt_info(item->pkgname, util_uri_to_path(inst->id), icon, name);
1013         } else if (item->widget.get_alt_info) {
1014                 ret = item->widget.get_alt_info(util_uri_to_path(inst->id), icon, name);
1015         } else {
1016                 ret = WIDGET_ERROR_NOT_SUPPORTED;
1017         }
1018         s_info.current_op = WIDGET_OP_UNKNOWN;
1019
1020         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
1021         if (ret >= 0) {
1022                 if (*icon) {
1023                         free(inst->icon);
1024                         inst->icon = *icon;
1025                 }
1026
1027                 if (*name) {
1028                         free(inst->name);
1029                         inst->name = *name;
1030                 }
1031         }
1032
1033         if (main_heap_monitor_is_enabled()) {
1034                 DbgPrint("%s allocates %d bytes\n", item->pkgname, main_heap_monitor_target_usage(item->so_fname));
1035         }
1036
1037         return ret;
1038 }
1039
1040 HAPI int so_get_output_info(struct instance *inst, int *w, int *h, double *priority, char **content, char **title)
1041 {
1042         struct so_item *item;
1043         int ret;
1044
1045         item = inst->item;
1046         if (!item) {
1047                 return WIDGET_ERROR_INVALID_PARAMETER;
1048         }
1049
1050         *content = NULL;
1051         *title = NULL;
1052
1053         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
1054
1055         s_info.current_op = WIDGET_OP_GET_INFO;
1056         if (item->adaptor.get_output_info) {
1057                 ret = item->adaptor.get_output_info(item->pkgname, util_uri_to_path(inst->id), w, h, priority, content, title);
1058         } else if (item->widget.get_output_info) {
1059                 ret = item->widget.get_output_info(util_uri_to_path(inst->id), w, h, priority, content, title);
1060         } else {
1061                 ret = WIDGET_ERROR_NOT_SUPPORTED;
1062         }
1063         s_info.current_op = WIDGET_OP_UNKNOWN;
1064
1065         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
1066         if (ret >= 0) {
1067                 inst->w = *w;
1068                 inst->h = *h;
1069                 inst->priority = *priority;
1070
1071                 /*!
1072                  * \todo
1073                  * Add "*content" "*title" address validation code.
1074                  * using mcheck?
1075                  */
1076
1077                 if (*content) {
1078                         free(inst->content);
1079                         inst->content = *content;
1080                 }
1081
1082                 if (*title) {
1083                         free(inst->title);
1084                         inst->title = *title;
1085                 }
1086         }
1087
1088         if (main_heap_monitor_is_enabled()) {
1089                 DbgPrint("%s allocates %d bytes\n", item->pkgname, main_heap_monitor_target_usage(item->so_fname));
1090         }
1091
1092         return ret;
1093 }
1094
1095 HAPI int so_sys_event(struct instance *inst, int event)
1096 {
1097         struct so_item *item;
1098         int ret;
1099
1100         item = inst->item;
1101         if (!item) {
1102                 return WIDGET_ERROR_INVALID_PARAMETER;
1103         }
1104
1105         fault_mark_call(item->pkgname, inst->id, __func__, USE_ALARM, DEFAULT_LIFE_TIMER);
1106
1107         s_info.current_op = WIDGET_OP_SYSTEM_EVENT;
1108         if (item->adaptor.sys_event) {
1109                 ret = item->adaptor.sys_event(item->pkgname, util_uri_to_path(inst->id), event);
1110         } else if (item->widget.sys_event) {
1111                 ret = item->widget.sys_event(util_uri_to_path(inst->id), event);
1112         } else {
1113                 ret = WIDGET_ERROR_NOT_SUPPORTED;
1114         }
1115         s_info.current_op = WIDGET_OP_UNKNOWN;
1116
1117         fault_unmark_call(item->pkgname, inst->id, __func__, USE_ALARM);
1118         return ret;
1119 }
1120
1121 HAPI enum current_operations so_current_op(void)
1122 {
1123         return s_info.current_op;
1124 }
1125
1126 /* End of a file */