2 * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <bundle_internal.h>
26 #include <glib-object.h>
28 #include <Elementary.h>
29 #include <widget_errno.h>
30 #include <widget_instance.h>
31 #include <aul_app_com.h>
32 #include <Ecore_Wayland.h>
33 #include <system_info.h>
35 #include <vconf-internal-keys.h>
36 #include <screen_connector_provider.h>
37 #include <appcore_multiwindow_base.h>
39 #include "widget_app.h"
40 #include "widget-log.h"
41 #include "widget-private.h"
42 #include "widget_app_internal.h"
48 #define LOG_TAG "CAPI_WIDGET_APPLICATION"
49 #define APP_TYPE_WIDGET "widgetapp"
50 #define STATUS_FOREGROUND "fg"
51 #define STATUS_BACKGROUND "bg"
61 struct widget_class_context {
62 widget_instance_lifecycle_callback_s callback;
66 struct widget_app_context {
67 widget_app_lifecycle_callback_s callback;
72 struct widget_foreach_context {
73 widget_context_cb callback;
77 struct app_event_info {
78 app_event_type_e type;
82 struct app_event_handler {
83 app_event_type_e type;
89 struct _widget_context {
93 static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
94 [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
95 [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
96 [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
97 [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
98 [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
99 [APP_EVENT_SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
102 static struct widget_app_context __context;
103 static char *__appid;
104 static char *__package_id;
105 static bool __fg_signal;
106 char *_viewer_endpoint;
108 static bool __is_widget_feature_enabled(void)
110 static bool feature = false;
111 static bool retrieved = false;
114 if (retrieved == true)
117 ret = system_info_get_platform_bool(
118 "http://tizen.org/feature/shell.appwidget", &feature);
119 if (ret != SYSTEM_INFO_ERROR_NONE) {
120 _E("failed to get system info"); /* LCOV_EXCL_LINE */
121 return false; /* LCOV_EXCL_LINE */
129 /* LCOV_EXCL_START */
130 static void __on_poweroff(keynode_t *key, void *data)
134 val = vconf_keynode_get_int(key);
136 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
137 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
138 _I("power off changed: %d", val);
141 case VCONFKEY_SYSMAN_POWER_OFF_NONE:
142 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
150 static int __widget_app_create(void *data)
152 char pkgid[256] = {0, };
154 appcore_multiwindow_base_on_create();
155 app_get_id(&__appid);
156 if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
157 __package_id = strdup(pkgid);
159 if (!__package_id || !__appid) {
160 _E("__package_id is NULL");
164 screen_connector_provider_init();
165 vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff, NULL);
167 if (__context.callback.create == NULL) {
168 _E("__context.callback.create(is NULL");
172 if (__context.callback.create(__context.data) == NULL) {
173 _E("app_create_cb() returns NULL");
177 _D("widget app is created");
181 static int __widget_app_terminate(void *data)
183 if (__context.callback.terminate)
184 __context.callback.terminate(__context.data);
186 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, __on_poweroff);
187 screen_connector_provider_fini();
189 if (_viewer_endpoint) {
190 free(_viewer_endpoint);
191 _viewer_endpoint = NULL;
204 appcore_multiwindow_base_on_terminate();
206 _D("widget app is terminated");
210 static int __send_lifecycle_event(const char *class_id, const char *instance_id,
213 bundle *b = bundle_create();
217 _E("out of memory"); /* LCOV_EXCL_LINE */
218 return -1; /* LCOV_EXCL_LINE */
221 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
222 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
223 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
224 bundle_add_str(b, AUL_K_PKGID, __package_id);
226 _D("send lifecycle %s(%d)", instance_id, status);
227 ret = aul_app_com_send("widget.status", b);
229 _E("send lifecycle error:%d", ret); /* LCOV_EXCL_LINE */
236 static int __send_update_status(const char *class_id, const char *instance_id,
237 int status, bundle *extra)
241 bundle_raw *raw = NULL;
246 _E("out of memory"); /* LCOV_EXCL_LINE */
247 return -1; /* LCOV_EXCL_LINE */
250 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
251 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
252 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
255 bundle_encode(extra, &raw, &len);
256 bundle_add_str(b, WIDGET_K_CONTENT_INFO, (const char *)raw);
257 aul_widget_instance_add(class_id, instance_id);
260 _D("send update %s(%d) to %s", instance_id, status, _viewer_endpoint);
261 aul_app_com_send(_viewer_endpoint, b);
264 case WIDGET_INSTANCE_EVENT_CREATE:
265 lifecycle = WIDGET_LIFE_CYCLE_EVENT_CREATE;
267 case WIDGET_INSTANCE_EVENT_DESTROY:
268 lifecycle = WIDGET_LIFE_CYCLE_EVENT_DESTROY;
270 case WIDGET_INSTANCE_EVENT_PAUSE:
271 lifecycle = WIDGET_LIFE_CYCLE_EVENT_PAUSE;
273 case WIDGET_INSTANCE_EVENT_RESUME:
274 lifecycle = WIDGET_LIFE_CYCLE_EVENT_RESUME;
279 __send_lifecycle_event(class_id, instance_id, lifecycle);
288 static void __instance_resume(const char *class_id, const char *id, bundle *b)
290 appcore_multiwindow_base_instance_h cxt;
292 cxt = appcore_multiwindow_base_instance_find(id);
295 _E("context not found: %s", id);
299 appcore_multiwindow_base_instance_resume(cxt);
301 __send_update_status(class_id, id,
302 WIDGET_INSTANCE_EVENT_RESUME, NULL);
304 _D("Send fg signal to resourceD");
305 aul_send_app_status_change_signal(getpid(),
314 static void __instance_pause(const char *class_id, const char *id, bundle *b)
316 appcore_multiwindow_base_instance_h cxt;
318 cxt = appcore_multiwindow_base_instance_find(id);
321 _E("context not found: %s", id);
325 appcore_multiwindow_base_instance_pause(cxt);
328 _D("Send bg signal to resourceD");
329 aul_send_app_status_change_signal(getpid(),
338 static void __instance_resize(const char *class_id, const char *id, bundle *b)
340 appcore_multiwindow_base_instance_h cxt;
341 struct widget_class_context *class_cxt;
342 const appcore_multiwindow_base_class *cls;
343 struct widget_extra *we;
350 cxt = appcore_multiwindow_base_instance_find(id);
353 _E("context not found: %s", id);
357 cls = appcore_multiwindow_base_instance_get_class(cxt);
361 class_cxt = cls->data;
367 we = appcore_multiwindow_base_instance_get_extra(cxt);
369 _E("widget extra is NULL");
373 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
374 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
377 w = (int)g_ascii_strtoll(w_str, &remain, 10);
380 h = (int)g_ascii_strtoll(h_str, &remain, 10);
383 evas_object_resize(we->win, w, h);
385 _E("unable to find window of %s", id);
387 if (class_cxt->callback.resize)
388 class_cxt->callback.resize(cxt, w, h, class_cxt->data);
389 _D("%s is resized to %dx%d", id, w, h);
390 __send_update_status(class_id, id,
391 WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL);
394 static void __inst_cb(const char *class_id, const char *id,
395 appcore_multiwindow_base_instance_h cxt, void *data)
397 struct widget_class_context *class_cxt;
398 const appcore_multiwindow_base_class *cls;
399 bundle *content = NULL;
400 char *content_raw = NULL;
401 char *force_str = NULL;
406 _E("bundle is NULL");
410 cls = appcore_multiwindow_base_instance_get_class(cxt);
416 class_cxt = cls->data;
418 _E("class context is NULL");
422 if (!class_cxt->callback.update) {
423 _E("update callback is NULL");
427 bundle_get_str(b, WIDGET_K_FORCE, &force_str);
429 if (force_str && strcmp(force_str, "true") == 0)
434 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw);
437 content = bundle_decode((const bundle_raw *)content_raw, strlen(content_raw));
438 class_cxt->callback.update(cxt, content, force, class_cxt->data);
439 __send_update_status(class_id, id,
440 WIDGET_INSTANCE_EVENT_UPDATE, NULL);
441 _D("updated:%s", id);
444 bundle_free(content);
447 static void __instance_update(const char *class_id, const char *id, bundle *b)
449 appcore_multiwindow_base_instance_h cxt;
452 appcore_multiwindow_base_instance_foreach(class_id, __inst_cb, b);
456 cxt = appcore_multiwindow_base_instance_find(id);
459 _E("context not found: %s", id);
463 __inst_cb(class_id, id, cxt, b);
466 static void __instance_create(const char *class_id, const char *id, bundle *b)
468 struct widget_extra *we;
469 char *content = NULL;
471 we = (struct widget_extra *)calloc(1, sizeof(struct widget_extra));
477 we->instance_id = strdup(id);
479 appcore_multiwindow_base_instance_run(class_id, id, we);
482 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
484 we->content = strdup(content);
488 static void __check_empty_instance(void)
490 int cnt = appcore_multiwindow_base_instance_get_cnt();
496 static void __instance_destroy(const char *class_id, const char *id, bundle *b)
498 appcore_multiwindow_base_instance_h cxt;
499 struct widget_extra *we;
501 cxt = appcore_multiwindow_base_instance_find(id);
503 _E("could not find widget obj: %s, clear amd info", id);
504 aul_widget_instance_del(class_id, id);
508 we = appcore_multiwindow_base_instance_get_extra(cxt);
510 appcore_multiwindow_base_instance_exit(cxt);
511 free(we->instance_id);
514 __check_empty_instance();
517 static int __widget_app_control(bundle *b, void *data)
519 char *class_id = NULL;
521 char *operation = NULL;
523 appcore_multiwindow_base_on_control(b);
525 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
526 /* for previous version compatibility, use appid for default class id */
527 if (class_id == NULL)
530 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
531 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
534 _E("operation is NULL");
538 if (strcmp(operation, "create") == 0) {
539 __instance_create(class_id, id, b);
540 } else if (strcmp(operation, "resize") == 0) {
541 __instance_resize(class_id, id, b);
542 } else if (strcmp(operation, "update") == 0) {
543 __instance_update(class_id, id, b);
544 } else if (strcmp(operation, "destroy") == 0) {
545 __instance_destroy(class_id, id, b);
546 } else if (strcmp(operation, "resume") == 0) {
547 __instance_resume(class_id, id, b);
548 } else if (strcmp(operation, "pause") == 0) {
549 __instance_pause(class_id, id, b);
550 } else if (strcmp(operation, "terminate") == 0) {
551 __instance_destroy(class_id, id, b);
557 static void __inst_resume_cb(const char *class_id, const char *id,
558 appcore_multiwindow_base_instance_h cxt, void *data)
560 __instance_resume(class_id, id, data);
563 static void __get_content(bundle *b)
565 char *instance_id = NULL;
566 appcore_multiwindow_base_instance_h cxt;
567 struct widget_extra *we;
569 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
571 _E("instance id is NULL");
575 cxt = appcore_multiwindow_base_instance_find(instance_id);
577 _E("could not find widget obj: %s", instance_id);
581 we = appcore_multiwindow_base_instance_get_extra(cxt);
583 _E("widget extra is NULL");
588 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content);
589 _D("content info of %s found", instance_id);
591 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, "");
592 _D("empty content info added");
596 static int __widget_app_receive(aul_type type, bundle *b, void *data)
598 appcore_multiwindow_base_on_receive(type, b);
602 appcore_multiwindow_base_instance_foreach_full(__inst_resume_cb, b);
607 case AUL_WIDGET_CONTENT:
617 EXPORT_API int widget_app_main(int argc, char **argv,
618 widget_app_lifecycle_callback_s *callback, void *user_data)
621 char *viewer_endpoint = NULL;
623 if (!__is_widget_feature_enabled()) {
624 _E("not supported"); /* LCOV_EXCL_LINE */
625 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
628 if (argc <= 0 || argv == NULL || callback == NULL)
629 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
632 if (__context.dirty) {
633 _E("Already started");
634 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
637 if (callback->create == NULL)
638 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
640 "widget_app_create_cb() callback must be "
643 appcore_multiwindow_base_ops ops = appcore_multiwindow_base_get_default_ops();
645 /* override methods */
646 ops.base.create = __widget_app_create;
647 ops.base.control = __widget_app_control;
648 ops.base.terminate = __widget_app_terminate;
649 ops.base.receive = __widget_app_receive;
650 __context.callback = *callback;
651 __context.data = user_data;
652 kb = bundle_import_from_argv(argc, argv);
654 bundle_get_str(kb, WIDGET_K_ENDPOINT, &viewer_endpoint);
655 if (viewer_endpoint) {
656 _D("viewer endpoint :%s", viewer_endpoint);
657 _viewer_endpoint = strdup(viewer_endpoint);
659 _E("endpoint is missing");
664 _E("failed to get launch argv"); /* LCOV_EXCL_LINE */
665 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
668 __context.dirty = true;
669 appcore_multiwindow_base_init(ops, argc, argv, NULL);
670 appcore_multiwindow_base_fini();
671 __context.dirty = false;
673 return WIDGET_ERROR_NONE;
676 EXPORT_API int widget_app_exit(void)
678 if (!__is_widget_feature_enabled()) {
679 _E("not supported"); /* LCOV_EXCL_LINE */
680 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
683 appcore_multiwindow_base_exit();
684 return WIDGET_ERROR_NONE;
687 static gboolean __finish_event_cb(gpointer user_data)
689 appcore_multiwindow_base_instance_h cxt = user_data;
692 const char *class_id;
695 _E("user_data is NULL");
699 id = appcore_multiwindow_base_instance_get_id(cxt);
700 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
708 bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
709 __instance_destroy(class_id, id, b);
715 EXPORT_API int widget_app_terminate_context(widget_context_h context)
717 if (!__is_widget_feature_enabled()) {
718 _E("not supported"); /* LCOV_EXCL_LINE */
719 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
723 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
726 g_idle_add(__finish_event_cb, context);
727 return WIDGET_ERROR_NONE;
730 static void __inst_full_cb(const char *class_id, const char *id,
731 appcore_multiwindow_base_instance_h cxt, void *data)
733 struct widget_foreach_context *foreach_context = data;
738 if (foreach_context->callback)
739 foreach_context->callback(cxt, foreach_context->data);
742 EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data)
744 struct widget_foreach_context foreach_context;
746 if (!__is_widget_feature_enabled()) {
747 _E("not supported"); /* LCOV_EXCL_LINE */
748 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
752 _E("callback is NULL");
753 return WIDGET_ERROR_INVALID_PARAMETER;
756 foreach_context.callback = cb;
757 foreach_context.data = data;
758 appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
760 return WIDGET_ERROR_NONE;
763 int __event_cb(void *event, void *data)
765 app_event_handler_h handler = data;
767 struct app_event_info app_event;
769 app_event.type = handler->type;
770 app_event.value = event;
773 handler->cb(&app_event, handler->data);
778 EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler,
779 app_event_type_e event_type, app_event_cb callback,
784 app_event_handler_h handler;
786 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
788 return WIDGET_ERROR_FAULT;
791 return WIDGET_ERROR_NOT_SUPPORTED;
793 if (event_handler == NULL || callback == NULL)
794 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
796 if (event_type < APP_EVENT_LOW_MEMORY
797 || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
798 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
800 if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
801 return widget_app_error(WIDGET_ERROR_NOT_SUPPORTED, __FUNCTION__, NULL);
804 handler = calloc(1, sizeof(struct app_event_handler));
806 return widget_app_error(WIDGET_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
808 handler->type = event_type;
809 handler->cb = callback;
810 handler->data = user_data;
811 handler->raw = appcore_base_add_event(__app_event_converter[event_type], __event_cb, handler);
812 *event_handler = handler;
814 return WIDGET_ERROR_NONE;
817 EXPORT_API int widget_app_remove_event_handler(app_event_handler_h
823 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
825 return WIDGET_ERROR_FAULT;
828 return WIDGET_ERROR_NOT_SUPPORTED;
830 app_event_type_e type;
832 if (event_handler == NULL)
833 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
835 type = event_handler->type;
836 if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED)
837 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
839 r = appcore_base_remove_event(event_handler->raw);
841 return widget_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid raw handler");
845 return WIDGET_ERROR_NONE;
848 EXPORT_API const char *widget_app_get_id(widget_context_h context)
850 if (!__is_widget_feature_enabled()) {
851 _E("not supported"); /* LCOV_EXCL_LINE */
852 set_last_result(WIDGET_ERROR_NOT_SUPPORTED); /* LCOV_EXCL_LINE */
853 return NULL; /* LCOV_EXCL_LINE */
857 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
861 set_last_result(WIDGET_ERROR_NONE);
862 return appcore_multiwindow_base_instance_get_id(context);
865 static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
868 plug_id = evas_object_data_del(obj, "___PLUGID");
872 EXPORT_API int widget_app_get_elm_win(widget_context_h context,
875 Evas_Object *ret_win;
876 Ecore_Wl_Window *wl_win;
877 struct wl_surface *surface;
878 struct widget_extra *we;
883 appcore_multiwindow_base_instance_h cxt;
885 if (!__is_widget_feature_enabled()) {
886 _E("not supported"); /* LCOV_EXCL_LINE */
887 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
890 if (context == NULL || win == NULL)
891 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
894 cxt = (appcore_multiwindow_base_instance_h)context;
895 id = appcore_multiwindow_base_instance_get_id(cxt);
896 ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC);
897 if (ret_win == NULL) {
898 _E("failed to create window"); /* LCOV_EXCL_LINE */
899 goto fault; /* LCOV_EXCL_LINE */
902 elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
903 elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
905 wl_win = elm_win_wl_window_get(ret_win);
906 if (wl_win == NULL) {
907 _E("failed to get wayland window"); /* LCOV_EXCL_LINE */
911 surface = ecore_wl_window_surface_get(wl_win);
912 if (surface == NULL) {
913 _E("failed to get surface"); /* LCOV_EXCL_LINE */
914 goto fault; /* LCOV_EXCL_LINE */
916 screen_connector_provider_remote_enable(id, surface);
918 ecore_wl_window_class_name_set(wl_win, id);
919 elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
922 we = appcore_multiwindow_base_instance_get_extra(cxt);
924 win_id = ecore_wl_window_id_get(wl_win);
926 /* Set data to use in accessibility */
927 snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid());
928 evas_object_data_set(ret_win, "___PLUGID", strdup(buffer));
929 evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL);
930 appcore_multiwindow_base_window_bind(cxt, ret_win);
932 _D("window created: %d", win_id);
934 return WIDGET_ERROR_NONE;
937 if (ret_win) /* LCOV_EXCL_LINE */
938 evas_object_del(ret_win); /* LCOV_EXCL_LINE */
940 return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */
943 static void __instance_drop(appcore_multiwindow_base_instance_h cxt)
945 struct widget_extra *we;
947 we = appcore_multiwindow_base_instance_get_extra(cxt);
948 appcore_multiwindow_base_instance_drop(cxt);
949 free(we->instance_id);
952 __check_empty_instance();
955 static void __stub_create(appcore_multiwindow_base_instance_h context, void *data)
957 struct widget_class_context *cxt = data;
958 struct widget_extra *we;
960 bundle *content_info = NULL;
962 char *class_id = NULL;
963 char *operation = NULL;
964 char *content = NULL;
972 appcore_multiwindow_base_class_on_create(context);
973 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
976 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
977 /* for previous version compatibility, use appid for default class id */
978 if (class_id == NULL)
981 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
982 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
985 _E("no operation provided");
989 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
990 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
991 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
994 w = (int)g_ascii_strtoll(w_str, &remain, 10);
997 h = (int)g_ascii_strtoll(h_str, &remain, 10);
1000 content_info = bundle_decode((const bundle_raw *)content, strlen(content));
1002 if (cxt->callback.create)
1003 ret = cxt->callback.create(context, content_info, w, h, cxt->data);
1004 _D("%s is created %d", id);
1007 _W("Create callback returns error(%d)", ret);
1008 ret = __send_update_status(class_id, id,
1009 WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL);
1010 __instance_drop(context);
1012 ret = __send_update_status(class_id, id,
1013 WIDGET_INSTANCE_EVENT_CREATE, NULL);
1015 aul_widget_instance_add(class_id, id);
1019 bundle_free(content_info);
1022 static void __stub_terminate(appcore_multiwindow_base_instance_h context, void *data)
1024 struct widget_class_context *class_cxt = data;
1025 struct widget_extra *we;
1027 char *operation = NULL;
1028 bundle *content_info;
1029 widget_app_destroy_type_e reason = WIDGET_APP_DESTROY_TYPE_TEMPORARY;
1030 int event = WIDGET_INSTANCE_EVENT_TERMINATE;
1032 const char *class_id;
1034 id = appcore_multiwindow_base_instance_get_id(context);
1035 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1036 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1040 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1041 if (operation && strcmp(operation, "destroy") == 0)
1042 reason = WIDGET_APP_DESTROY_TYPE_PERMANENT;
1046 content_info = bundle_decode((const bundle_raw *)we->content, strlen(we->content));
1048 content_info = bundle_create();
1050 if (class_cxt->callback.destroy)
1051 class_cxt->callback.destroy(context, reason, content_info, class_cxt->data);
1052 _D("%s is destroyed %d", id, reason);
1054 if (reason == WIDGET_APP_DESTROY_TYPE_PERMANENT) {
1055 event = WIDGET_INSTANCE_EVENT_DESTROY;
1056 aul_widget_instance_del(class_id, id);
1058 __send_update_status(class_id, id,
1059 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1063 bundle_free(content_info);
1065 __send_update_status(class_id, id, event, NULL);
1066 appcore_multiwindow_base_class_on_terminate(context);
1069 static void __stub_pause(appcore_multiwindow_base_instance_h context, void *data)
1071 struct widget_class_context *class_cxt = data;
1073 const char *class_id;
1075 appcore_multiwindow_base_class_on_pause(context);
1076 id = appcore_multiwindow_base_instance_get_id(context);
1077 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1080 _E("class context is NULL");
1084 if (class_cxt->callback.pause)
1085 class_cxt->callback.pause(context, class_cxt->data);
1086 _D("%s is paused", id);
1087 __send_update_status(class_id, id,
1088 WIDGET_INSTANCE_EVENT_PAUSE, NULL);
1091 static void __stub_resume(appcore_multiwindow_base_instance_h context, void *data)
1093 struct widget_class_context *class_cxt = data;
1095 const char *class_id;
1097 appcore_multiwindow_base_class_on_resume(context);
1098 id = appcore_multiwindow_base_instance_get_id(context);
1099 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1102 _E("class context is NULL");
1106 if (class_cxt->callback.resume)
1107 class_cxt->callback.resume(context, class_cxt->data);
1108 _D("%s is resumed", id);
1109 __send_update_status(class_id, id,
1110 WIDGET_INSTANCE_EVENT_RESUME, NULL);
1113 EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class,
1114 const char *class_id,
1115 widget_instance_lifecycle_callback_s callback, void *user_data)
1117 appcore_multiwindow_base_class cls;
1118 struct widget_class_context *cxt;
1120 if (!__is_widget_feature_enabled()) {
1121 _E("not supported");
1122 set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
1127 _E("class is is NULL");
1128 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
1132 cxt = calloc(1, sizeof(struct widget_class_context));
1135 _E("failed to calloc : %s", __FUNCTION__);
1136 set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
1140 cxt->callback = callback;
1141 cxt->data = user_data;
1143 cls.id = strdup(class_id);
1145 cls.create = __stub_create;
1146 cls.terminate = __stub_terminate;
1147 cls.pause = __stub_pause;
1148 cls.resume = __stub_resume;
1150 appcore_multiwindow_base_class_add(cls);
1151 set_last_result(WIDGET_ERROR_NONE);
1153 return (widget_class_h)cxt;
1156 EXPORT_API widget_class_h widget_app_class_create(
1157 widget_instance_lifecycle_callback_s callback, void *user_data)
1159 return widget_app_class_add(NULL, __appid, callback, user_data);
1162 EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag)
1164 struct widget_extra *we;
1166 if (!__is_widget_feature_enabled()) {
1167 _E("not supported"); /* LCOV_EXCL_LINE */
1168 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1172 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1173 __FUNCTION__, NULL);
1175 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1178 return WIDGET_ERROR_NONE;
1181 EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag)
1183 struct widget_extra *we;
1185 if (!__is_widget_feature_enabled()) {
1186 _E("not supported"); /* LCOV_EXCL_LINE */
1187 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1190 if (!context || !tag)
1191 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1192 __FUNCTION__, NULL);
1194 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1196 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1197 __FUNCTION__, NULL);
1200 return WIDGET_ERROR_NONE;
1203 EXPORT_API int widget_app_context_set_content_info(widget_context_h context,
1204 bundle *content_info)
1207 bundle_raw *raw = NULL;
1210 const char *class_id;
1211 struct widget_extra *we;
1212 appcore_multiwindow_base_instance_h cxt;
1214 if (!__is_widget_feature_enabled()) {
1215 _E("not supported"); /* LCOV_EXCL_LINE */
1216 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1219 if (!context || !content_info)
1220 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1221 __FUNCTION__, NULL);
1223 cxt = (appcore_multiwindow_base_instance_h)context;
1224 id = appcore_multiwindow_base_instance_get_id(cxt);
1225 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
1226 we = appcore_multiwindow_base_instance_get_extra(cxt);
1228 if (!class_id || !id || !we)
1229 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
1231 ret = __send_update_status(class_id, id,
1232 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1237 bundle_encode(content_info, &raw, &len);
1239 we->content = strdup((const char *)raw);
1245 /* LCOV_EXCL_START */
1246 _E("failed to send content info: %s of %s (%d)", id,
1248 return widget_app_error(WIDGET_ERROR_IO_ERROR, __FUNCTION__,
1250 /* LCOV_EXCL_STOP */
1253 return WIDGET_ERROR_NONE;
1256 EXPORT_API int widget_app_context_set_title(widget_context_h context,
1259 appcore_multiwindow_base_instance_h cxt;
1260 struct widget_extra *we;
1262 if (!__is_widget_feature_enabled()) {
1263 _E("not supported"); /* LCOV_EXCL_LINE */
1264 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1267 if (!context || !title) {
1268 _E("Invalid parameter %p %p", context, title);
1269 return WIDGET_ERROR_INVALID_PARAMETER;
1272 cxt = (appcore_multiwindow_base_instance_h)context;
1273 we = appcore_multiwindow_base_instance_get_extra(cxt);
1276 elm_win_title_set(we->win, title);
1278 return WIDGET_ERROR_NONE;