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 aul_widget_notify_exit();
686 return WIDGET_ERROR_NONE;
689 static gboolean __finish_event_cb(gpointer user_data)
691 appcore_multiwindow_base_instance_h cxt = user_data;
694 const char *class_id;
697 _E("user_data is NULL");
701 id = appcore_multiwindow_base_instance_get_id(cxt);
702 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
710 bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
711 __instance_destroy(class_id, id, b);
717 EXPORT_API int widget_app_terminate_context(widget_context_h context)
719 if (!__is_widget_feature_enabled()) {
720 _E("not supported"); /* LCOV_EXCL_LINE */
721 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
725 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
728 g_idle_add(__finish_event_cb, context);
729 return WIDGET_ERROR_NONE;
732 static void __inst_full_cb(const char *class_id, const char *id,
733 appcore_multiwindow_base_instance_h cxt, void *data)
735 struct widget_foreach_context *foreach_context = data;
740 if (foreach_context->callback)
741 foreach_context->callback(cxt, foreach_context->data);
744 EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data)
746 struct widget_foreach_context foreach_context;
748 if (!__is_widget_feature_enabled()) {
749 _E("not supported"); /* LCOV_EXCL_LINE */
750 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
754 _E("callback is NULL");
755 return WIDGET_ERROR_INVALID_PARAMETER;
758 foreach_context.callback = cb;
759 foreach_context.data = data;
760 appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
762 return WIDGET_ERROR_NONE;
765 int __event_cb(void *event, void *data)
767 app_event_handler_h handler = data;
769 struct app_event_info app_event;
771 app_event.type = handler->type;
772 app_event.value = event;
775 handler->cb(&app_event, handler->data);
780 EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler,
781 app_event_type_e event_type, app_event_cb callback,
786 app_event_handler_h handler;
788 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
790 return WIDGET_ERROR_FAULT;
793 return WIDGET_ERROR_NOT_SUPPORTED;
795 if (event_handler == NULL || callback == NULL)
796 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
798 if (event_type < APP_EVENT_LOW_MEMORY
799 || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
800 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
802 if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
803 return widget_app_error(WIDGET_ERROR_NOT_SUPPORTED, __FUNCTION__, NULL);
806 handler = calloc(1, sizeof(struct app_event_handler));
808 return widget_app_error(WIDGET_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
810 handler->type = event_type;
811 handler->cb = callback;
812 handler->data = user_data;
813 handler->raw = appcore_base_add_event(__app_event_converter[event_type], __event_cb, handler);
814 *event_handler = handler;
816 return WIDGET_ERROR_NONE;
819 EXPORT_API int widget_app_remove_event_handler(app_event_handler_h
825 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
827 return WIDGET_ERROR_FAULT;
830 return WIDGET_ERROR_NOT_SUPPORTED;
832 app_event_type_e type;
834 if (event_handler == NULL)
835 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
837 type = event_handler->type;
838 if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED)
839 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
841 r = appcore_base_remove_event(event_handler->raw);
843 return widget_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid raw handler");
847 return WIDGET_ERROR_NONE;
850 EXPORT_API const char *widget_app_get_id(widget_context_h context)
852 if (!__is_widget_feature_enabled()) {
853 _E("not supported"); /* LCOV_EXCL_LINE */
854 set_last_result(WIDGET_ERROR_NOT_SUPPORTED); /* LCOV_EXCL_LINE */
855 return NULL; /* LCOV_EXCL_LINE */
859 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
863 set_last_result(WIDGET_ERROR_NONE);
864 return appcore_multiwindow_base_instance_get_id(context);
867 static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
870 plug_id = evas_object_data_del(obj, "___PLUGID");
874 EXPORT_API int widget_app_get_elm_win(widget_context_h context,
877 Evas_Object *ret_win;
878 Ecore_Wl_Window *wl_win;
879 struct wl_surface *surface;
880 struct widget_extra *we;
885 appcore_multiwindow_base_instance_h cxt;
887 if (!__is_widget_feature_enabled()) {
888 _E("not supported"); /* LCOV_EXCL_LINE */
889 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
892 if (context == NULL || win == NULL)
893 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
896 cxt = (appcore_multiwindow_base_instance_h)context;
897 id = appcore_multiwindow_base_instance_get_id(cxt);
898 ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC);
899 if (ret_win == NULL) {
900 _E("failed to create window"); /* LCOV_EXCL_LINE */
901 goto fault; /* LCOV_EXCL_LINE */
904 elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
905 elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
907 wl_win = elm_win_wl_window_get(ret_win);
908 if (wl_win == NULL) {
909 _E("failed to get wayland window"); /* LCOV_EXCL_LINE */
913 surface = ecore_wl_window_surface_get(wl_win);
914 if (surface == NULL) {
915 _E("failed to get surface"); /* LCOV_EXCL_LINE */
916 goto fault; /* LCOV_EXCL_LINE */
918 screen_connector_provider_remote_enable(id, surface);
920 ecore_wl_window_class_name_set(wl_win, id);
921 elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
924 we = appcore_multiwindow_base_instance_get_extra(cxt);
926 win_id = ecore_wl_window_id_get(wl_win);
928 /* Set data to use in accessibility */
929 snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid());
930 evas_object_data_set(ret_win, "___PLUGID", strdup(buffer));
931 evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL);
932 appcore_multiwindow_base_window_bind(cxt, ret_win);
934 _D("window created: %d", win_id);
936 return WIDGET_ERROR_NONE;
939 if (ret_win) /* LCOV_EXCL_LINE */
940 evas_object_del(ret_win); /* LCOV_EXCL_LINE */
942 return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */
945 static void __instance_drop(appcore_multiwindow_base_instance_h cxt)
947 struct widget_extra *we;
949 we = appcore_multiwindow_base_instance_get_extra(cxt);
950 appcore_multiwindow_base_instance_drop(cxt);
951 free(we->instance_id);
954 __check_empty_instance();
957 static void __stub_create(appcore_multiwindow_base_instance_h context, void *data)
959 struct widget_class_context *cxt = data;
960 struct widget_extra *we;
962 bundle *content_info = NULL;
964 char *class_id = NULL;
965 char *operation = NULL;
966 char *content = NULL;
974 appcore_multiwindow_base_class_on_create(context);
975 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
978 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
979 /* for previous version compatibility, use appid for default class id */
980 if (class_id == NULL)
983 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
984 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
987 _E("no operation provided");
991 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
992 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
993 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
996 w = (int)g_ascii_strtoll(w_str, &remain, 10);
999 h = (int)g_ascii_strtoll(h_str, &remain, 10);
1002 content_info = bundle_decode((const bundle_raw *)content, strlen(content));
1004 if (cxt->callback.create)
1005 ret = cxt->callback.create(context, content_info, w, h, cxt->data);
1006 _D("%s is created %d", id);
1009 _W("Create callback returns error(%d)", ret);
1010 ret = __send_update_status(class_id, id,
1011 WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL);
1012 __instance_drop(context);
1014 ret = __send_update_status(class_id, id,
1015 WIDGET_INSTANCE_EVENT_CREATE, NULL);
1017 aul_widget_instance_add(class_id, id);
1021 bundle_free(content_info);
1024 static void __stub_terminate(appcore_multiwindow_base_instance_h context, void *data)
1026 struct widget_class_context *class_cxt = data;
1027 struct widget_extra *we;
1029 char *operation = NULL;
1030 bundle *content_info;
1031 widget_app_destroy_type_e reason = WIDGET_APP_DESTROY_TYPE_TEMPORARY;
1032 int event = WIDGET_INSTANCE_EVENT_TERMINATE;
1034 const char *class_id;
1036 id = appcore_multiwindow_base_instance_get_id(context);
1037 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1038 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1042 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1043 if (operation && strcmp(operation, "destroy") == 0)
1044 reason = WIDGET_APP_DESTROY_TYPE_PERMANENT;
1048 content_info = bundle_decode((const bundle_raw *)we->content, strlen(we->content));
1050 content_info = bundle_create();
1052 if (class_cxt->callback.destroy)
1053 class_cxt->callback.destroy(context, reason, content_info, class_cxt->data);
1054 _D("%s is destroyed %d", id, reason);
1056 if (reason == WIDGET_APP_DESTROY_TYPE_PERMANENT) {
1057 event = WIDGET_INSTANCE_EVENT_DESTROY;
1058 aul_widget_instance_del(class_id, id);
1060 __send_update_status(class_id, id,
1061 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1065 bundle_free(content_info);
1067 __send_update_status(class_id, id, event, NULL);
1068 appcore_multiwindow_base_class_on_terminate(context);
1071 static void __stub_pause(appcore_multiwindow_base_instance_h context, void *data)
1073 struct widget_class_context *class_cxt = data;
1075 const char *class_id;
1077 appcore_multiwindow_base_class_on_pause(context);
1078 id = appcore_multiwindow_base_instance_get_id(context);
1079 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1082 _E("class context is NULL");
1086 if (class_cxt->callback.pause)
1087 class_cxt->callback.pause(context, class_cxt->data);
1088 _D("%s is paused", id);
1089 __send_update_status(class_id, id,
1090 WIDGET_INSTANCE_EVENT_PAUSE, NULL);
1093 static void __stub_resume(appcore_multiwindow_base_instance_h context, void *data)
1095 struct widget_class_context *class_cxt = data;
1097 const char *class_id;
1099 appcore_multiwindow_base_class_on_resume(context);
1100 id = appcore_multiwindow_base_instance_get_id(context);
1101 class_id = appcore_multiwindow_base_instance_get_class_id(context);
1104 _E("class context is NULL");
1108 if (class_cxt->callback.resume)
1109 class_cxt->callback.resume(context, class_cxt->data);
1110 _D("%s is resumed", id);
1111 __send_update_status(class_id, id,
1112 WIDGET_INSTANCE_EVENT_RESUME, NULL);
1115 EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class,
1116 const char *class_id,
1117 widget_instance_lifecycle_callback_s callback, void *user_data)
1119 appcore_multiwindow_base_class cls;
1120 struct widget_class_context *cxt;
1122 if (!__is_widget_feature_enabled()) {
1123 _E("not supported");
1124 set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
1129 _E("class is is NULL");
1130 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
1134 cxt = calloc(1, sizeof(struct widget_class_context));
1137 _E("failed to calloc : %s", __FUNCTION__);
1138 set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
1142 cxt->callback = callback;
1143 cxt->data = user_data;
1145 cls.id = strdup(class_id);
1147 cls.create = __stub_create;
1148 cls.terminate = __stub_terminate;
1149 cls.pause = __stub_pause;
1150 cls.resume = __stub_resume;
1152 appcore_multiwindow_base_class_add(cls);
1153 set_last_result(WIDGET_ERROR_NONE);
1155 return (widget_class_h)cxt;
1158 EXPORT_API widget_class_h widget_app_class_create(
1159 widget_instance_lifecycle_callback_s callback, void *user_data)
1161 return widget_app_class_add(NULL, __appid, callback, user_data);
1164 EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag)
1166 struct widget_extra *we;
1168 if (!__is_widget_feature_enabled()) {
1169 _E("not supported"); /* LCOV_EXCL_LINE */
1170 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1174 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1175 __FUNCTION__, NULL);
1177 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1180 return WIDGET_ERROR_NONE;
1183 EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag)
1185 struct widget_extra *we;
1187 if (!__is_widget_feature_enabled()) {
1188 _E("not supported"); /* LCOV_EXCL_LINE */
1189 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1192 if (!context || !tag)
1193 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1194 __FUNCTION__, NULL);
1196 we = appcore_multiwindow_base_instance_get_extra((appcore_multiwindow_base_instance_h)context);
1198 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1199 __FUNCTION__, NULL);
1202 return WIDGET_ERROR_NONE;
1205 EXPORT_API int widget_app_context_set_content_info(widget_context_h context,
1206 bundle *content_info)
1209 bundle_raw *raw = NULL;
1212 const char *class_id;
1213 struct widget_extra *we;
1214 appcore_multiwindow_base_instance_h cxt;
1216 if (!__is_widget_feature_enabled()) {
1217 _E("not supported"); /* LCOV_EXCL_LINE */
1218 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1221 if (!context || !content_info)
1222 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
1223 __FUNCTION__, NULL);
1225 cxt = (appcore_multiwindow_base_instance_h)context;
1226 id = appcore_multiwindow_base_instance_get_id(cxt);
1227 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
1228 we = appcore_multiwindow_base_instance_get_extra(cxt);
1230 if (!class_id || !id || !we)
1231 return widget_app_error(WIDGET_ERROR_FAULT, __FUNCTION__, NULL);
1233 ret = __send_update_status(class_id, id,
1234 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
1239 bundle_encode(content_info, &raw, &len);
1241 we->content = strdup((const char *)raw);
1247 /* LCOV_EXCL_START */
1248 _E("failed to send content info: %s of %s (%d)", id,
1250 return widget_app_error(WIDGET_ERROR_IO_ERROR, __FUNCTION__,
1252 /* LCOV_EXCL_STOP */
1255 return WIDGET_ERROR_NONE;
1258 EXPORT_API int widget_app_context_set_title(widget_context_h context,
1261 appcore_multiwindow_base_instance_h cxt;
1262 struct widget_extra *we;
1264 if (!__is_widget_feature_enabled()) {
1265 _E("not supported"); /* LCOV_EXCL_LINE */
1266 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1269 if (!context || !title) {
1270 _E("Invalid parameter %p %p", context, title);
1271 return WIDGET_ERROR_INVALID_PARAMETER;
1274 cxt = (appcore_multiwindow_base_instance_h)context;
1275 we = appcore_multiwindow_base_instance_get_extra(cxt);
1278 elm_win_title_set(we->win, title);
1280 return WIDGET_ERROR_NONE;