Refactor appcore-widget 36/254936/29
authorjh9216.park <jh9216.park@samsung.com>
Thu, 11 Mar 2021 01:29:38 +0000 (20:29 -0500)
committerChanggyu Choi <changyu.choi@samsung.com>
Fri, 7 Jan 2022 07:22:39 +0000 (16:22 +0900)
 - Use app-core for C++

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/app-core/+/247812/
 - https://review.tizen.org/gerrit/#/c/platform/core/api/app-common/+/253882/

Change-Id: Ib0b43977c3334cb3942f26bf93c42de933448c24
Signed-off-by: jh9216.park <jh9216.park@samsung.com>
35 files changed:
CMakeLists.txt
appcore-widget-base.pc.in [deleted file]
appcore-widget.manifest [deleted file]
capi-appfw-widget-application.pc.in [deleted file]
include/widget_app.h [changed mode: 0755->0644]
include/widget_base.h
include/widget_base.hh [new file with mode: 0644]
packaging/appcore-widget.manifest [new file with mode: 0644]
packaging/appcore-widget.spec
src/base/CMakeLists.txt
src/base/appcore-widget-base.pc.in [new file with mode: 0644]
src/base/widget_base.c [deleted file]
src/base/widget_base.cc [new file with mode: 0644]
src/base/widget_base_legacy.c [new file with mode: 0644]
src/common/export_private.hh [new file with mode: 0644]
src/common/log_private.hh [new file with mode: 0644]
src/efl_base/CMakeLists.txt
src/efl_base/capi-appfw-widget-application.pc.in [new file with mode: 0644]
src/efl_base/widget-log.h [deleted file]
src/efl_base/widget-private.h [deleted file]
src/efl_base/widget_app.c [deleted file]
src/efl_base/widget_app.cc [new file with mode: 0644]
src/efl_base/widget_app_internal.c [deleted file]
src/efl_base/widget_error.c [deleted file]
test/unit_tests/CMakeLists.txt
test/unit_tests/mock/app_common_mock.h
test/unit_tests/mock/appcore_multiwindow_base_mock.cc
test/unit_tests/mock/appcore_multiwindow_base_mock.h
test/unit_tests/mock/aul_mock.cc
test/unit_tests/mock/aul_mock.h
test/unit_tests/mock/elm_mock.cc
test/unit_tests/mock/widget_service_mock.cc [new file with mode: 0644]
test/unit_tests/mock/widget_service_mock.h [new file with mode: 0644]
test/unit_tests/test_widget_app.cc
test/unit_tests/test_widget_app_cpp.cc

index 7dc63e6c957b1d938ac4cada54621f727e71f3fb..a35ef8d5fbac43cb14117c71209233542bdbaa13 100644 (file)
@@ -8,12 +8,15 @@ SET(LIBDIR ${LIB_INSTALL_DIR})
 SET(INCLUDEDIR "\${prefix}/include")
 
 ## Compiler flags
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -g -Wall -Werror")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -Werror")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
 
 ## Linker flags
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed,--gc-sections -pie")
 
-SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
 
 ## Targets
 SET(TARGET_WIDGET_BASE "appcore-widget-base")
@@ -28,26 +31,21 @@ INCLUDE(ApplyPkgConfig)
 ADD_DEFINITIONS("-DPROJECT_TAG=\"TIZEN_APPCORE_WIDGET\"")
 
 ## Find all needed packages once
+PKG_CHECK_MODULES(APPCORE_COMMON_DEPS REQUIRED app-core-cpp)
+PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_DEPS REQUIRED app-core-multi-window-cpp)
+PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_OLD_DEPS REQUIRED appcore-multiwindow)
+PKG_CHECK_MODULES(AUL_DEP REQUIRED aul)
 PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle)
+PKG_CHECK_MODULES(CAPI_APP_COMMON_DEP REQUIRED capi-appfw-app-common)
 PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog)
-PKG_CHECK_MODULES(APPCORE_COMMON_DEPS REQUIRED appcore-common)
-PKG_CHECK_MODULES(WIDGET_SERVICE_DEPS REQUIRED widget_service)
-PKG_CHECK_MODULES(SYSTEM_INFO_DEPS REQUIRED capi-system-info)
 PKG_CHECK_MODULES(ECORE_WL2_DEPS REQUIRED ecore-wl2)
-PKG_CHECK_MODULES(SCREEN_CONNECTOR_PROVIDER_DEPS REQUIRED screen_connector_provider)
-PKG_CHECK_MODULES(APPCORE_MULTIWINDOW_DEPS REQUIRED appcore-multiwindow)
-PKG_CHECK_MODULES(AUL_DEP REQUIRED aul)
 PKG_CHECK_MODULES(ELEMENTARY_DEP REQUIRED elementary)
-PKG_CHECK_MODULES(CAPI_APP_COMMON_DEP REQUIRED capi-appfw-app-common)
 PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0)
-PKG_CHECK_MODULES(GOBJECT_DEPS REQUIRED gobject-2.0)
 PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock)
+PKG_CHECK_MODULES(GOBJECT_DEPS REQUIRED gobject-2.0)
+PKG_CHECK_MODULES(SCREEN_CONNECTOR_PROVIDER_DEPS REQUIRED screen_connector_provider)
+PKG_CHECK_MODULES(SYSTEM_INFO_DEPS REQUIRED capi-system-info)
+PKG_CHECK_MODULES(WIDGET_SERVICE_DEPS REQUIRED widget_service)
 
 ADD_SUBDIRECTORY(src)
 ADD_SUBDIRECTORY(test)
-
-
-
-
-
-
diff --git a/appcore-widget-base.pc.in b/appcore-widget-base.pc.in
deleted file mode 100644 (file)
index f2d3717..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Package Information for pkg-config
-
-prefix=@PREFIX@
-exec_prefix=@EXEC_PREFIX@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCLUDEDIR@
-
-Name: appcore-widget-base
-Description: widget base library
-Version: @VERSION@
-Requires: aul dlog capi-appfw-app-common widget_service appcore-multiwindow
-Libs: -L${libdir} -lappcore-widget-base
-Cflags: -I${includedir} -I${includedir}/appfw
diff --git a/appcore-widget.manifest b/appcore-widget.manifest
deleted file mode 100644 (file)
index 97e8c31..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<manifest>
-       <request>
-               <domain name="_"/>
-       </request>
-</manifest>
diff --git a/capi-appfw-widget-application.pc.in b/capi-appfw-widget-application.pc.in
deleted file mode 100644 (file)
index 6f7ec01..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Package Information for pkg-config
-
-prefix=@PREFIX@
-exec_prefix=@EXEC_PREFIX@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCLUDEDIR@
-
-Name: capi-appfw-widget-application
-Description: widget application library
-Version: @VERSION@
-Requires.private: aul dlog elementary capi-appfw-app-common widget_service
-Requires: appcore-widget-base
-Libs: -L${libdir} -lcapi-appfw-widget-application
-Cflags: -I${includedir} -I${includedir}/appfw
old mode 100755 (executable)
new mode 100644 (file)
index 80e1a576f17c49fb49fea1e651d7c9cd1ff918b0..769c5660422f24776809144a6e99ad53982ce22c 100644 (file)
 extern "C" {
 #endif
 
+/* Deprecated APIs. Please use widget_base.hh */
+
+#define WIDGE_BASE_DEPRECATED __attribute__ ((deprecated))
+
 typedef enum widget_base_destroy_type {
        WIDGET_BASE_DESTROY_TYPE_PERMANENT = 0x00,
        WIDGET_BASE_DESTROY_TYPE_TEMPORARY = 0x01,
@@ -85,50 +89,50 @@ typedef struct _widget_base_class {
 
 typedef bool (*widget_base_instance_cb)(widget_base_instance_h instance, void *data);
 
-int widget_base_foreach_context(widget_base_instance_cb cb, void *data);
-int widget_base_terminate_context(widget_base_instance_h instance_h);
+int widget_base_foreach_context(widget_base_instance_cb cb, void *data) WIDGE_BASE_DEPRECATED;
+int widget_base_terminate_context(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED;
 int widget_base_add_event_handler(app_event_handler_h *event_handler,
                                        app_event_type_e event_type,
                                        app_event_cb callback,
-                                       void *user_data);
+                                       void *user_data) WIDGE_BASE_DEPRECATED;
 int widget_base_remove_event_handler(app_event_handler_h
-                                               event_handler);
+                                               event_handler) WIDGE_BASE_DEPRECATED;
 int widget_base_context_set_content_info(widget_base_instance_h instance_h,
-               bundle *content_info);
-int widget_base_context_get_tag(widget_base_instance_h instance_h, void **tag);
-int widget_base_context_set_tag(widget_base_instance_h instance_h, void *tag);
-void *widget_base_context_get_user_data(widget_base_instance_h instance_h);
+               bundle *content_info) WIDGE_BASE_DEPRECATED;
+int widget_base_context_get_tag(widget_base_instance_h instance_h, void **tag) WIDGE_BASE_DEPRECATED;
+int widget_base_context_set_tag(widget_base_instance_h instance_h, void *tag) WIDGE_BASE_DEPRECATED;
+void *widget_base_context_get_user_data(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED;
 int widget_base_context_set_user_data(widget_base_instance_h instance_h,
-               void *user_data);
-int widget_base_context_get_id(widget_base_instance_h instance_h, char **id);
-const char *widget_base_get_viewer_endpoint(void);
-int widget_base_init(widget_base_ops ops, int argc, char **argv, void *data);
-int widget_base_on_create(void);
-int widget_base_on_terminate(void);
-int widget_base_on_init(int argc, char **argv);
-void widget_base_on_finish(void);
-void widget_base_on_run(void);
-void widget_base_on_exit(void);
-int widget_base_on_trim_memory(void);
-widget_base_ops widget_base_get_default_ops(void);
-void widget_base_fini(void);
-int widget_base_exit(void);
+               void *user_data) WIDGE_BASE_DEPRECATED;
+int widget_base_context_get_id(widget_base_instance_h instance_h, char **id) WIDGE_BASE_DEPRECATED;
+const char *widget_base_get_viewer_endpoint(void) WIDGE_BASE_DEPRECATED;
+int widget_base_init(widget_base_ops ops, int argc, char **argv, void *data) WIDGE_BASE_DEPRECATED;
+int widget_base_on_create(void) WIDGE_BASE_DEPRECATED;
+int widget_base_on_terminate(void) WIDGE_BASE_DEPRECATED;
+int widget_base_on_init(int argc, char **argv) WIDGE_BASE_DEPRECATED;
+void widget_base_on_finish(void) WIDGE_BASE_DEPRECATED;
+void widget_base_on_run(void) WIDGE_BASE_DEPRECATED;
+void widget_base_on_exit(void) WIDGE_BASE_DEPRECATED;
+int widget_base_on_trim_memory(void) WIDGE_BASE_DEPRECATED;
+widget_base_ops widget_base_get_default_ops(void) WIDGE_BASE_DEPRECATED;
+void widget_base_fini(void) WIDGE_BASE_DEPRECATED;
+int widget_base_exit(void) WIDGE_BASE_DEPRECATED;
 int widget_base_context_window_bind(
                widget_base_instance_h instance_h, const char *id,
-               Ecore_Wl2_Window *wl_win);
+               Ecore_Wl2_Window *wl_win) WIDGE_BASE_DEPRECATED;
 int widget_base_class_on_create(widget_base_instance_h instance_h,
-               bundle *content, int w, int h);
-int widget_base_class_on_pause(widget_base_instance_h instance_h);
-int widget_base_class_on_resume(widget_base_instance_h instance_h);
+               bundle *content, int w, int h) WIDGE_BASE_DEPRECATED;
+int widget_base_class_on_pause(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED;
+int widget_base_class_on_resume(widget_base_instance_h instance_h) WIDGE_BASE_DEPRECATED;
 int widget_base_class_on_resize(widget_base_instance_h instance_h,
-               int w, int h);
+               int w, int h) WIDGE_BASE_DEPRECATED;
 int widget_base_class_on_update(widget_base_instance_h instance_h,
-               bundle *content, int force);
+               bundle *content, int force) WIDGE_BASE_DEPRECATED;
 int widget_base_class_on_destroy(widget_base_instance_h instance_h,
-               widget_base_destroy_type_e reason, bundle *content);
-widget_base_class widget_base_class_get_default(void);
+               widget_base_destroy_type_e reason, bundle *content) WIDGE_BASE_DEPRECATED;
+widget_base_class widget_base_class_get_default(void) WIDGE_BASE_DEPRECATED;
 widget_base_class *widget_base_class_add(widget_base_class cls,
-               const char *class_id, void *class_data);
+               const char *class_id, void *class_data) WIDGE_BASE_DEPRECATED;
 
 #ifdef __cplusplus
 }
diff --git a/include/widget_base.hh b/include/widget_base.hh
new file mode 100644 (file)
index 0000000..8f0c043
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIDGET_BASE_HH_
+#define WIDGET_BASE_HH_
+
+#include <app_common.h>
+
+#include <memory>
+#include <string>
+
+#include <app_core_multi_window_base.hh>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace tizen_cpp {
+
+class EXPORT_API WidgetBase : public AppCoreMultiWindowBase {
+ public:
+  WidgetBase();
+  virtual ~WidgetBase();
+
+  std::string GetViewerEndpoint();
+  void Run(int argc, char** argv) override;
+  void Exit() override;
+  int OnControl(tizen_base::Bundle b) override;
+  int OnCreate() override;
+  int OnTerminate() override;
+  int OnReceive(aul_type type, tizen_base::Bundle b) override;
+  void ExitContext(std::shared_ptr<Context> context) override;
+
+ protected:
+  void Dispose() override;
+
+ private:
+  friend class WidgetContext;
+  class Impl;
+  std::unique_ptr<Impl> impl_;
+};
+
+class EXPORT_API WidgetContext : public AppCoreMultiWindowBase::Context {
+ public:
+  enum class DestroyType {
+    PERMANENT,
+    TEMPORARY
+  };
+
+  WidgetContext(std::string context_id, std::string inst_id,
+      AppCoreMultiWindowBase* app);
+  virtual ~WidgetContext();
+  virtual bool OnCreate(const tizen_base::Bundle& contents, int w, int h) = 0;
+  virtual void OnDestroy(DestroyType reason,
+      const tizen_base::Bundle& contents) = 0;
+  virtual void OnPause();
+  virtual void OnResume();
+  virtual void OnResize(int w, int h);
+  virtual void OnUpdate(const tizen_base::Bundle& contents, bool force);
+  void ExitAsync();
+  int SetContents(const tizen_base::Bundle& contents);
+  int WindowBind(std::string id, Ecore_Wl2_Window* wl_win);
+
+ private:
+  using AppCoreMultiWindowBase::Context::WindowBind;
+  void OnCreate() override;
+  void OnTerminate() override;
+
+ private:
+  friend class WidgetBase;
+  class Impl;
+  std::unique_ptr<Impl> impl_;
+};
+
+}  // namespace tizen_cpp
+
+#endif  // WIDGET_BASE_HH_
diff --git a/packaging/appcore-widget.manifest b/packaging/appcore-widget.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
index b84fa3232ffebdf4b21c50363c3686f347c0fdcb..a750a1a8aef426b263624e64114aa7c00b208144 100644 (file)
@@ -4,15 +4,17 @@ Version:    1.3.14
 Release:    1
 Group:      Application Framework/Libraries
 License:    Apache-2.0
-Source0:    appcore-widget-%{version}.tar.gz
+Source0:    %{name}-%{version}.tar.gz
+Source1001: %{name}.manifest
 BuildRequires:  pkgconfig(aul)
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(elementary)
-BuildRequires:  pkgconfig(appcore-common)
+BuildRequires:  pkgconfig(app-core-cpp)
 BuildRequires:  pkgconfig(capi-appfw-app-common)
 BuildRequires:  pkgconfig(widget_service)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(ecore-wl2)
+BuildRequires:  pkgconfig(app-core-multi-window-cpp)
 BuildRequires:  pkgconfig(appcore-multiwindow)
 BuildRequires:  pkgconfig(screen_connector_provider)
 BuildRequires:  pkgconfig(gmock)
@@ -71,6 +73,7 @@ gcov objects of a widget application library
 
 %prep
 %setup -q
+cp %{SOURCE1001} .
 
 %build
 %if 0%{?gcov:1}
@@ -99,9 +102,6 @@ mkdir -p %{buildroot}%{_datadir}/gcov/obj
 install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
 %endif
 
-mkdir -p %{buildroot}%{_libdir}/pkgconfig
-cp capi-appfw-widget-application.pc %{buildroot}%{_libdir}/pkgconfig
-
 %check
 export LD_LIBRARY_PATH=../../src/base:../../src/efl_base
 ctest -V
@@ -123,11 +123,11 @@ install -m 0644 appcore-widget.zip %{buildroot}%{_datadir}/gcov/
 %license LICENSE
 
 %files -n appcore-widget-base-devel
+/usr/include/appfw/widget_base.hh
 /usr/include/appfw/widget_base.h
 %{_libdir}/pkgconfig/appcore-widget-base.pc
 %{_libdir}/libappcore-widget-base.so
 
-
 %files -n appcore-widget
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
index 13314c52bbbafc559c79d162626069e20e9b5bcb..eccf4f2bce7629ede88ad393c5f305d66b74c011 100644 (file)
@@ -4,8 +4,12 @@ ADD_LIBRARY(${TARGET_WIDGET_BASE} SHARED ${WIDGET_BASE_SRCS})
 SET_TARGET_PROPERTIES(${TARGET_WIDGET_BASE} PROPERTIES SOVERSION ${MAJORVER})
 SET_TARGET_PROPERTIES(${TARGET_WIDGET_BASE} PROPERTIES VERSION ${FULLVER})
 
-TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
-TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include/)
+TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_BASE} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../common/)
 
 APPLY_PKG_CONFIG(${TARGET_WIDGET_BASE} PUBLIC
   DLOG_DEPS
@@ -15,9 +19,13 @@ APPLY_PKG_CONFIG(${TARGET_WIDGET_BASE} PUBLIC
   ECORE_WL2_DEPS
   SCREEN_CONNECTOR_PROVIDER_DEPS
   APPCORE_MULTIWINDOW_DEPS
+  APPCORE_MULTIWINDOW_OLD_DEPS
   CAPI_APP_COMMON_DEP
 )
 
-CONFIGURE_FILE(../../appcore-widget-base.pc.in ../../appcore-widget-base.pc @ONLY)
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/appcore-widget-base.pc.in
+  ${CMAKE_CURRENT_SOURCE_DIR}/appcore-widget-base.pc @ONLY)
 INSTALL(TARGETS ${TARGET_WIDGET_BASE} DESTINATION ${LIB_INSTALL_DIR})
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../appcore-widget-base.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/appcore-widget-base.pc
+  DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw/)
diff --git a/src/base/appcore-widget-base.pc.in b/src/base/appcore-widget-base.pc.in
new file mode 100644 (file)
index 0000000..53779bf
--- /dev/null
@@ -0,0 +1,13 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDEDIR@
+
+Name: appcore-widget-base
+Description: widget base library
+Version: @VERSION@
+Requires: aul dlog capi-appfw-app-common widget_service appcore-multiwindow app-core-multi-window-cpp
+Libs: -L${libdir} -lappcore-widget-base
+Cflags: -I${includedir} -I${includedir}/appfw
diff --git a/src/base/widget_base.c b/src/base/widget_base.c
deleted file mode 100644 (file)
index ec0d02d..0000000
+++ /dev/null
@@ -1,1580 +0,0 @@
-/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include <bundle.h>
-#include <bundle_internal.h>
-#include <aul.h>
-#include <aul_widget.h>
-#include <dlog.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <widget_errno.h>
-#include <widget_instance.h>
-#include <aul_app_com.h>
-#include <Ecore_Wl2.h>
-#include <system_info.h>
-#include <screen_connector_provider.h>
-#include <appcore_multiwindow_base.h>
-
-#include "widget_base.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_WIDGET_APPLICATION"
-#define APP_TYPE_WIDGET "widgetapp"
-#define STATUS_FOREGROUND "fg"
-#define STATUS_BACKGROUND "bg"
-
-static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
-       [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
-       [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
-       [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
-       [APP_EVENT_DEVICE_ORIENTATION_CHANGED]
-                       = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
-       [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
-       [APP_EVENT_SUSPENDED_STATE_CHANGED]
-                       = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
-};
-
-struct app_event_info {
-       app_event_type_e type;
-       void *value;
-};
-
-struct app_event_handler {
-       app_event_type_e type;
-       app_event_cb cb;
-       void *data;
-       void *raw;
-};
-
-struct widget_foreach_context {
-       widget_base_instance_cb callback;
-       void *data;
-};
-
-typedef struct _widget_base_context {
-       widget_base_ops ops;
-       void *data;
-       int argc;
-       char **argv;
-       GList *classes;
-} widget_base_context;
-
-typedef struct _widget_base_instance_data {
-       bundle *args;
-       char *id;
-       char *content;
-       void *tag;
-       double period;
-       guint periodic_timer;
-       bool pending_update;
-       char *pending_content;
-       void *user_data;
-} widget_base_instance_data;
-
-static widget_base_context __context;
-static char *__appid;
-static char *__package_id;
-static bool __fg_signal;
-static char *__viewer_endpoint;
-static bool __is_permanent;
-static void __call_update_cb(const char *class_id, const char *id, int force,
-               const char *content_raw);
-
-static gboolean __timeout_cb(gpointer user_data)
-{
-       widget_base_instance_data *data =
-                       (widget_base_instance_data *)user_data;
-       appcore_multiwindow_base_instance_h cxt;
-       const char *class_id;
-
-       cxt = appcore_multiwindow_base_instance_find(data->id);
-
-       if (!cxt) {
-               LOGE("Can't find the instance");
-               return G_SOURCE_REMOVE;
-       }
-
-       if (appcore_multiwindow_base_instance_is_resumed(cxt)) {
-               LOGD("Periodic update!");
-               class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
-               __call_update_cb(class_id, data->id, 0, NULL);
-       } else {
-               data->pending_update = true;
-               if (data->periodic_timer) {
-                       LOGD("Remove timer!");
-                       g_source_remove(data->periodic_timer);
-                       data->periodic_timer = 0;
-               }
-       }
-
-       return G_SOURCE_CONTINUE;
-}
-
-static bool __is_widget_feature_enabled(void)
-{
-       static bool feature = false;
-       static bool retrieved = false;
-       int ret;
-
-       if (retrieved == true)
-               return feature;
-
-       ret = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
-       if (ret != SYSTEM_INFO_ERROR_NONE) {
-               LOGE("failed to get system info"); /* LCOV_EXCL_LINE */
-               return false; /* LCOV_EXCL_LINE */
-       }
-
-       retrieved = true;
-
-       return feature;
-}
-
-static void __check_empty_instance(void)
-{
-       int cnt = appcore_multiwindow_base_instance_get_cnt();
-
-       if (cnt == 0)
-               widget_base_exit();
-}
-
-static void __instance_drop(appcore_multiwindow_base_instance_h instance_h)
-{
-       widget_base_instance_data *data;
-
-       data = appcore_multiwindow_base_instance_get_extra(instance_h);
-       appcore_multiwindow_base_instance_drop(instance_h);
-       free(data->pending_content);
-       free(data->content);
-       free(data->id);
-       free(data);
-       __check_empty_instance();
-}
-
-static gint __comp_class(gconstpointer a, gconstpointer b)
-{
-       const widget_base_class *cls = a;
-
-       return strcmp(cls->id, b);
-}
-
-static widget_base_class *__get_class(const char *class_id)
-{
-       widget_base_class *cls;
-       GList *class_node;
-
-       class_node = g_list_find_custom(__context.classes, class_id,
-                       __comp_class);
-       if (class_node == NULL) {
-               LOGE("empty classes");
-               return NULL;
-       }
-       cls = (widget_base_class *)class_node->data;
-
-       return cls;
-}
-
-static int __send_update_status(const char *class_id, const char *instance_id,
-       int status, int err, bundle *extra)
-{
-       int lifecycle;
-
-       aul_widget_send_status_to_viewer(class_id, instance_id,
-                       __viewer_endpoint, status, err, extra);
-       lifecycle = widget_instance_convert_event_to_lifecycle_status(status);
-       if (lifecycle > -1) {
-               aul_widget_send_status_to_service(
-                               class_id, instance_id, __package_id, lifecycle);
-       }
-
-       return 0;
-}
-
-static void __control_create(const char *class_id, const char *id, bundle *b)
-{
-       widget_base_instance_data *data;
-       char *content = NULL;
-
-       if (appcore_multiwindow_base_instance_find(id)) {
-               LOGE("Already exist id (%s)", id);
-               return;
-       }
-
-       data = (widget_base_instance_data *)
-                       calloc(1, sizeof(widget_base_instance_data));
-       if (!data) {
-               LOGE("Out of memory");
-               return;
-       }
-
-       data->id = strdup(id);
-       data->args = b;
-
-       /* call stub create */
-       appcore_multiwindow_base_instance_run(class_id, id, data);
-       if (appcore_multiwindow_base_instance_find(id)) {
-               data->args = NULL;
-               bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
-               if (content)
-                       data->content = strdup(content);
-       }
-}
-
-static void __control_resume(const char *class_id, const char *id, bundle *b)
-{
-       appcore_multiwindow_base_instance_h cxt;
-
-       cxt = appcore_multiwindow_base_instance_find(id);
-       if (!cxt) {
-               LOGE("context not found: %s", id);
-               return;
-       }
-
-       /* call stub resume */
-       appcore_multiwindow_base_instance_resume(cxt);
-}
-
-static void __control_pause(const char *class_id, const char *id, bundle *b)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-
-       if (!instance_h) {
-               LOGE("instance not found: %s", id);
-               return;
-       }
-
-       /* call stub pause */
-       appcore_multiwindow_base_instance_pause(instance_h);
-}
-
-static void __control_resize(const char *class_id, const char *id, bundle *b)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       char *remain = NULL;
-       char *w_str = NULL;
-       char *h_str = NULL;
-       int w = 0;
-       int h = 0;
-       void *class_data;
-       widget_base_class *cls;
-       const appcore_multiwindow_base_class *raw_cls;
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-       if (!instance_h) {
-               LOGE("context not found: %s", id);
-               return;
-       }
-
-       raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
-       if (!raw_cls)
-               return;
-
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-       class_data = raw_cls->data;
-       bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
-       bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
-
-       if (w_str)
-               w = (int)g_ascii_strtoll(w_str, &remain, 10);
-
-       if (h_str)
-               h = (int)g_ascii_strtoll(h_str, &remain, 10);
-
-       if (cls->ops.resize)
-               cls->ops.resize(instance_h, w, h, class_data);
-
-       LOGD("%s is resized to %dx%d", id, w, h);
-       __send_update_status(class_id, id,
-               WIDGET_INSTANCE_EVENT_SIZE_CHANGED, 0, NULL);
-}
-
-static void __call_update_cb(const char *class_id, const char *id, int force,
-               const char *content_raw)
-{
-       void *class_data;
-       widget_base_class *cls;
-       const appcore_multiwindow_base_class *raw_cls;
-       appcore_multiwindow_base_instance_h instance_h;
-       bundle *content = NULL;
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-       if (!instance_h) {
-               LOGE("context not found: %s", id);
-               return;
-       }
-
-       raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
-       if (!raw_cls) {
-               LOGE("class is NULL");
-               return;
-       }
-
-       class_data = raw_cls->data;
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-
-       if (!cls->ops.update) {
-               LOGE("update callback is NULL");
-               return;
-       }
-
-       if (content_raw) {
-               content = bundle_decode((const bundle_raw *)content_raw,
-                               strlen(content_raw));
-       }
-
-       if (cls->ops.update)
-               cls->ops.update(instance_h, content, force, class_data);
-
-       __send_update_status(class_id, id,
-               WIDGET_INSTANCE_EVENT_UPDATE, 0, NULL);
-       LOGD("updated:%s", id);
-
-       if (content)
-               bundle_free(content);
-}
-
-static void __update_pending_content(
-               appcore_multiwindow_base_instance_h instance_h,
-               const char *content_raw)
-{
-       widget_base_instance_data *data;
-
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       if (data->pending_content) {
-               free(data->pending_content);
-               data->pending_content = NULL;
-       }
-
-       if (content_raw) {
-               data->pending_content = strdup(content_raw);
-               if (data->pending_content == NULL)
-                       LOGW("Out of memory");
-       }
-
-       data->pending_update = true;
-}
-
-static void __update_process(const char *class_id, const char *id,
-               appcore_multiwindow_base_instance_h instance_h, void *data)
-{
-       char *content_raw = NULL;
-       char *force_str = NULL;
-       int force;
-       bundle *b = data;
-
-       if (!b) {
-               LOGE("bundle is NULL");
-               return;
-       }
-
-       bundle_get_str(b, WIDGET_K_FORCE, &force_str);
-
-       if (force_str && strcmp(force_str, "true") == 0)
-               force = 1;
-       else
-               force = 0;
-
-       bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw);
-       if (!appcore_multiwindow_base_instance_is_resumed(instance_h) && !force)
-               __update_pending_content(instance_h, content_raw);
-       else
-               __call_update_cb(class_id, id, force, content_raw);
-}
-
-static void __control_update(const char *class_id, const char *id, bundle *b)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-
-       if (!id) {
-               appcore_multiwindow_base_instance_foreach(class_id,
-                               __update_process, b);
-               return;
-       }
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-       if (!instance_h) {
-               LOGE("context not found: %s", id);
-               return;
-       }
-
-       __update_process(class_id, id, instance_h, b);
-}
-
-static void __control_destroy(const char *class_id, const char *id, bundle *b)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-       if (!instance_h) {
-               LOGE("could not find widget obj: %s, clear amd info", id);
-               aul_widget_instance_del(class_id, id);
-               return;
-       }
-
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-       data->args = b;
-
-       /* call stub terminate */
-       appcore_multiwindow_base_instance_exit(instance_h);
-       free(data->pending_content);
-       free(data->content);
-       free(data->id);
-       free(data);
-       __check_empty_instance();
-       aul_widget_write_log(LOG_TAG,
-               "[%s:%d] instance_id(%s)", __FUNCTION__, __LINE__, id);
-}
-
-static void __control_change_period(const char *class_id, const char *id,
-               bundle *b)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-       double *period = NULL;
-       size_t size;
-       int ret;
-
-       instance_h = appcore_multiwindow_base_instance_find(id);
-       if (!instance_h) {
-               LOGE("context not found: %s", id);
-               return;
-       }
-
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       if (!data) {
-               LOGE("could not find instance data: %s", id);
-               return;
-       }
-
-       if (data->periodic_timer) {
-               LOGD("Remove timer!");
-               g_source_remove(data->periodic_timer);
-               data->periodic_timer = 0;
-       }
-
-       ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size);
-       if (ret == BUNDLE_ERROR_NONE)
-               data->period = *period;
-
-       if (data->period > 0) {
-               LOGD("Restart timer!");
-               data->periodic_timer = g_timeout_add_seconds(data->period,
-                               __timeout_cb, data);
-       }
-
-       return;
-}
-
-static int __multiwindow_create(void *data)
-{
-       char pkgid[256] = {0, };
-       int ret = 0;
-
-       appcore_multiwindow_base_on_create();
-       app_get_id(&__appid);
-       if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
-               __package_id = strdup(pkgid);
-
-       if (!__package_id || !__appid) {
-               LOGE("__package_id is NULL");
-               return -1;
-       }
-
-       screen_connector_provider_init();
-       if (__context.ops.create)
-               ret = __context.ops.create(data);
-
-       LOGD("widget base is created");
-       return ret;
-}
-
-static int __multiwindow_terminate(void *data)
-{
-       if (__context.ops.terminate)
-               __context.ops.terminate(data);
-       screen_connector_provider_fini();
-
-       if (__viewer_endpoint) {
-               free(__viewer_endpoint);
-               __viewer_endpoint = NULL;
-       }
-
-       if (__package_id) {
-               free(__package_id);
-               __package_id = NULL;
-       }
-
-       if (__appid) {
-               free(__appid);
-               __appid = NULL;
-       }
-
-       appcore_multiwindow_base_on_terminate();
-
-       LOGD("widget base is terminated");
-       return 0;
-}
-
-static int __multiwindow_control(bundle *b, void *data)
-{
-       char *class_id = NULL;
-       char *id = NULL;
-       char *operation = NULL;
-
-       appcore_multiwindow_base_on_control(b);
-       bundle_get_str(b, WIDGET_K_CLASS, &class_id);
-       /* for previous version compatibility, use appid for default class id */
-       if (class_id == NULL)
-               class_id = __appid;
-
-       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
-       bundle_get_str(b, WIDGET_K_OPERATION, &operation);
-
-       if (!operation) {
-               LOGE("operation is NULL");
-               return 0;
-       }
-
-       LOGI("app control operation(%s)", operation);
-       if (strcmp(operation, "create") == 0)
-               __control_create(class_id, id, b);
-       else if (strcmp(operation, "resize") == 0)
-               __control_resize(class_id, id, b);
-       else if (strcmp(operation, "update") == 0)
-               __control_update(class_id, id, b);
-       else if (strcmp(operation, "destroy") == 0)
-               __control_destroy(class_id, id, b);
-       else if (strcmp(operation, "resume") == 0)
-               __control_resume(class_id, id, b);
-       else if (strcmp(operation, "pause") == 0)
-               __control_pause(class_id, id, b);
-       else if (strcmp(operation, "terminate") == 0)
-               __control_destroy(class_id, id, b);
-       else if (strcmp(operation, "period") == 0)
-               __control_change_period(class_id, id, b);
-
-       return 0;
-}
-
-static void __inst_resume_cb(const char *class_id, const char *id,
-               appcore_multiwindow_base_instance_h cxt, void *data)
-{
-       __control_resume(class_id, id, data);
-}
-
-static void __get_content(bundle *b)
-{
-       char *instance_id = NULL;
-       appcore_multiwindow_base_instance_h cxt;
-       widget_base_instance_data * we;
-
-       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
-       if (!instance_id) {
-               LOGE("instance id is NULL");
-               return;
-       }
-
-       cxt = appcore_multiwindow_base_instance_find(instance_id);
-       if (!cxt) {
-               LOGE("could not find widget obj: %s", instance_id);
-               return;
-       }
-
-       we = appcore_multiwindow_base_instance_get_extra(cxt);
-       if (!we) {
-               LOGE("widget extra is NULL");
-               return;
-       }
-
-       if (we->content) {
-               bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content);
-               LOGD("content info of %s found", instance_id);
-       } else {
-               bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, "");
-               LOGD("empty content info added");
-       }
-}
-
-static int __multiwindow_receive(aul_type type, bundle *b, void *data)
-{
-       appcore_multiwindow_base_on_receive(type, b);
-
-       switch (type) {
-       case AUL_RESUME:
-               appcore_multiwindow_base_instance_foreach_full(
-                               __inst_resume_cb, b);
-               break;
-       case AUL_TERMINATE:
-               widget_base_exit();
-               break;
-       case AUL_WIDGET_CONTENT:
-               __get_content(b);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static void __multiwindow_init(int argc, char **argv, void *data)
-{
-       if (__context.ops.init)
-               __context.ops.init(argc, argv, data);
-}
-
-static void __multiwindow_finish(void)
-{
-       if (__context.ops.finish) {
-               __context.ops.finish();
-               /* Check Loader case */
-               if (getenv("AUL_LOADER_INIT")) {
-                       unsetenv("AUL_LOADER_INIT");
-                       __context.ops.finish();
-               }
-       }
-}
-
-static void __multiwindow_run(void *data)
-{
-       if (__context.ops.run)
-               __context.ops.run(data);
-}
-
-static void __multiwindow_exit(void *data)
-{
-       if (__context.ops.exit)
-               __context.ops.exit(data);
-}
-
-static void __multiwindow_trim_memory(void *data)
-{
-       if (__context.ops.trim_memory)
-               __context.ops.trim_memory(data);
-}
-
-EXPORT_API int widget_base_exit(void)
-{
-       int ret = 0;
-       int cnt;
-
-       appcore_multiwindow_base_exit();
-       cnt = appcore_multiwindow_base_instance_get_cnt();
-       if (cnt == 0 && __is_permanent)
-               ret = aul_notify_exit();
-
-       aul_widget_write_log(LOG_TAG,
-               "[%s:%d] exit : ret(%d), cnt(%d), permanent(%d)",
-                       __FUNCTION__, __LINE__, ret, cnt, __is_permanent);
-
-       return 0;
-}
-
-static gboolean __finish_event_cb(gpointer user_data)
-{
-       appcore_multiwindow_base_instance_h cxt = user_data;
-       bundle *b;
-       const char *id;
-       const char *class_id;
-
-       if (!cxt) {
-               LOGE("user_data is NULL");
-               return FALSE;
-       }
-
-       id = appcore_multiwindow_base_instance_get_id(cxt);
-       class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
-       b = bundle_create();
-
-       if (!b) {
-               LOGE("Out-of-memory");
-               return FALSE;
-       }
-
-       bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
-       __control_destroy(class_id, id, b);
-       bundle_free(b);
-
-       return FALSE;
-}
-
-EXPORT_API int widget_base_terminate_context(widget_base_instance_h context)
-{
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context) {
-               LOGE("context is null");
-               return WIDGET_ERROR_INVALID_PARAMETER;
-       }
-
-       g_idle_add(__finish_event_cb, context);
-
-       return WIDGET_ERROR_NONE;
-}
-
-static void __inst_full_cb(const char *class_id, const char *id,
-               appcore_multiwindow_base_instance_h cxt, void *data)
-{
-       struct widget_foreach_context *foreach_context = data;
-
-       if (!data)
-               return;
-
-       if (foreach_context->callback)
-               foreach_context->callback(cxt, foreach_context->data);
-}
-
-EXPORT_API int widget_base_foreach_context(widget_base_instance_cb cb, void *data)
-{
-       struct widget_foreach_context foreach_context;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!cb) {
-               LOGE("callback is NULL");
-               return WIDGET_ERROR_INVALID_PARAMETER;
-       }
-
-       foreach_context.callback = cb;
-       foreach_context.data = data;
-       appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
-
-       return WIDGET_ERROR_NONE;
-}
-
-static int __event_cb(void *event, void *data)
-{
-       app_event_handler_h handler = data;
-
-       struct app_event_info app_event;
-
-       app_event.type = handler->type;
-       app_event.value = event;
-
-       if (handler->cb)
-               handler->cb(&app_event, handler->data);
-
-       return 0;
-}
-
-EXPORT_API int widget_base_add_event_handler(app_event_handler_h *event_handler,
-                                       app_event_type_e event_type,
-                                       app_event_cb callback,
-                                       void *user_data)
-{
-       int r;
-       bool feature;
-       app_event_handler_h handler;
-
-       r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
-       if (r < 0)
-               return WIDGET_BASE_ERROR_FAULT;
-
-       if (!feature)
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
-
-       if (event_handler == NULL || callback == NULL)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       if (event_type < APP_EVENT_LOW_MEMORY
-           || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
-
-
-       handler = calloc(1, sizeof(struct app_event_handler));
-       if (!handler)
-               return WIDGET_BASE_ERROR_OUT_OF_MEMORY;
-
-       handler->type = event_type;
-       handler->cb = callback;
-       handler->data = user_data;
-       handler->raw = appcore_base_add_event(
-                       __app_event_converter[event_type], __event_cb, handler);
-       *event_handler = handler;
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API int widget_base_remove_event_handler(app_event_handler_h
-                                               event_handler)
-{
-       int r;
-       bool feature;
-       app_event_type_e type;
-
-       r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
-       if (r < 0)
-               return WIDGET_BASE_ERROR_FAULT;
-
-       if (!feature)
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
-
-       if (event_handler == NULL)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       type = event_handler->type;
-       if (type < APP_EVENT_LOW_MEMORY ||
-                       type > APP_EVENT_REGION_FORMAT_CHANGED)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       r = appcore_base_remove_event(event_handler->raw);
-       if (r < 0)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       free(event_handler);
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API int widget_base_context_set_content_info(
-               widget_base_instance_h context,
-               bundle *content_info)
-{
-       int ret = 0;
-       bundle_raw *raw = NULL;
-       int len;
-       const char *id;
-       const char *class_id;
-       widget_base_instance_data *data;
-       appcore_multiwindow_base_instance_h instance_h;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context || !content_info)
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       id = appcore_multiwindow_base_instance_get_id(instance_h);
-       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
-       data = appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       if (!class_id || !id || !data)
-               return WIDGET_BASE_ERROR_FAULT;
-
-       ret = __send_update_status(class_id, id,
-                       WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, content_info);
-
-       if (data->content)
-               free(data->content);
-
-       bundle_encode(content_info, &raw, &len);
-       if (raw)
-               data->content = strdup((const char *)raw);
-       else
-               data->content = NULL;
-
-       free(raw);
-       if (ret < 0) {
-               /* LCOV_EXCL_START */
-               LOGE("failed to send content info: %s of %s (%d)", id,
-                               class_id, ret);
-               return WIDGET_BASE_ERROR_IO_ERROR;
-               /* LCOV_EXCL_STOP */
-       }
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API int widget_base_context_get_tag(widget_base_instance_h context, void **tag)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context || !tag) {
-               LOGE("Invalid parameter");
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-       }
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       if (!data) {
-               LOGE("Invalid parameter");
-               return WIDGET_ERROR_INVALID_PARAMETER;
-       }
-
-       *tag = data->tag;
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API int widget_base_context_set_tag(widget_base_instance_h context, void *tag)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context) {
-               LOGE("Invalid parameter");
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-       }
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-       data->tag = tag;
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API void *widget_base_context_get_user_data(
-               widget_base_instance_h context)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return NULL; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context) {
-               LOGE("Invalid parameter");
-               return NULL;
-       }
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       return data->user_data;
-}
-
-
-EXPORT_API int widget_base_context_set_user_data(
-               widget_base_instance_h context, void *user_data)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-       widget_base_instance_data *data;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       if (!context) {
-               LOGE("Invalid parameter");
-               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
-       }
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-       data->user_data = user_data;
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API int widget_base_context_get_id(widget_base_instance_h context, char **id)
-{
-       appcore_multiwindow_base_instance_h instance_h;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       instance_h = (appcore_multiwindow_base_instance_h)context;
-       *id = (char *)appcore_multiwindow_base_instance_get_id(instance_h);
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-EXPORT_API const char *widget_base_get_viewer_endpoint()
-{
-       return __viewer_endpoint;
-}
-
-EXPORT_API int widget_base_init(widget_base_ops ops, int argc, char **argv,
-               void *data)
-{
-       bundle *kb;
-       char *viewer_endpoint = NULL;
-       appcore_multiwindow_base_ops raw_ops
-                       = appcore_multiwindow_base_get_default_ops();
-
-       __context.ops = ops;
-       __context.argc = argc;
-       __context.argv = argv;
-       __context.data = data;
-
-       /* override methods */
-       raw_ops.base.create = __multiwindow_create;
-       raw_ops.base.control = __multiwindow_control;
-       raw_ops.base.terminate = __multiwindow_terminate;
-       raw_ops.base.receive = __multiwindow_receive;
-       raw_ops.base.init = __multiwindow_init;
-       raw_ops.base.finish = __multiwindow_finish;
-       raw_ops.base.run = __multiwindow_run;
-       raw_ops.base.exit = __multiwindow_exit;
-       raw_ops.base.trim_memory = __multiwindow_trim_memory;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported"); /* LCOV_EXCL_LINE */
-               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
-       }
-
-       kb = bundle_import_from_argv(argc, argv);
-       if (kb) {
-               bundle_get_str(kb, AUL_K_WIDGET_VIEWER, &viewer_endpoint);
-               if (viewer_endpoint) {
-                       LOGD("viewer endpoint :%s", viewer_endpoint);
-                       __viewer_endpoint = strdup(viewer_endpoint);
-               } else {
-                       LOGE("endpoint is missing");
-               }
-
-               bundle_free(kb);
-       } else {
-               LOGE("failed to get launch argv"); /* LCOV_EXCL_LINE */
-               return WIDGET_ERROR_FAULT;
-       }
-
-       if (appcore_multiwindow_base_init(raw_ops, argc, argv, data) < 0)
-              return WIDGET_ERROR_FAULT;
-
-       return WIDGET_ERROR_NONE;
-}
-
-static int __on_create(void *data)
-{
-       return widget_base_on_create();
-}
-
-static int __on_terminate(void *data)
-{
-       return widget_base_on_terminate();
-}
-
-static void __on_init(int argc, char **argv, void *data)
-{
-       widget_base_on_init(argc, argv);
-}
-
-static void __on_finish(void)
-{
-       widget_base_on_finish();
-}
-
-static void __on_run(void *data)
-{
-       widget_base_on_run();
-}
-
-static void __on_exit(void *data)
-{
-       widget_base_on_exit();
-}
-
-static void __on_trim_memory(void *data)
-{
-       widget_base_on_trim_memory();
-}
-
-EXPORT_API int widget_base_on_create(void)
-{
-       appcore_multiwindow_base_on_create();
-
-       return 0;
-}
-
-EXPORT_API int widget_base_on_terminate(void)
-{
-       appcore_multiwindow_base_on_terminate();
-
-       return 0;
-}
-
-EXPORT_API int widget_base_on_init(int argc, char **argv)
-{
-       return 0;
-}
-
-EXPORT_API void widget_base_on_finish(void)
-{
-}
-
-EXPORT_API void widget_base_on_run(void)
-{
-}
-
-EXPORT_API void widget_base_on_exit(void)
-{
-}
-
-EXPORT_API int widget_base_on_trim_memory(void)
-{
-       appcore_multiwindow_base_on_trim_memory();
-
-       return 0;
-}
-
-EXPORT_API widget_base_ops widget_base_get_default_ops(void)
-{
-       widget_base_ops ops;
-
-       /* override methods */
-       ops.create = __on_create;
-       ops.terminate = __on_terminate;
-       ops.init = __on_init;
-       ops.finish = __on_finish;
-       ops.run = __on_run;
-       ops.exit = __on_exit;
-       ops.trim_memory = __on_trim_memory;
-
-       return ops;
-}
-
-static void __free_class(gpointer data)
-{
-       widget_base_class *cls = data;
-
-       free(cls->id);
-       free(cls);
-}
-
-EXPORT_API void widget_base_fini(void)
-{
-       appcore_multiwindow_base_fini();
-       g_list_free_full(__context.classes, __free_class);
-       __context.classes = NULL;
-}
-
-EXPORT_API int widget_base_context_window_bind(
-               widget_base_instance_h instance_h, const char *id,
-               Ecore_Wl2_Window *wl_win)
-{
-       struct wl_surface *surface;
-
-       surface = ecore_wl2_window_surface_get(wl_win);
-       if (surface == NULL) {
-               LOGE("failed to get surface"); /* LCOV_EXCL_LINE */
-               return WIDGET_BASE_ERROR_FAULT; /* LCOV_EXCL_LINE */
-       }
-
-       screen_connector_provider_remote_enable(id, surface);
-       appcore_multiwindow_base_window_bind(instance_h, wl_win);
-
-       return WIDGET_BASE_ERROR_NONE;
-}
-
-static int __class_on_create(widget_base_instance_h instance_h, bundle *content,
-               int w, int h, void *class_data)
-{
-       return widget_base_class_on_create(instance_h, content, w, h);
-}
-
-static int __class_on_resume(widget_base_instance_h instance_h,        void *class_data)
-{
-       return widget_base_class_on_resume(instance_h);
-}
-
-static int __class_on_pause(widget_base_instance_h instance_h,
-               void *class_data)
-{
-       return widget_base_class_on_pause(instance_h);
-}
-
-static int __class_on_resize(widget_base_instance_h instance_h, int w, int h,
-               void *class_data)
-{
-       return widget_base_class_on_resize(instance_h, w, h);
-}
-
-static int __class_on_update(widget_base_instance_h instance_h, bundle *content,
-               int force, void *class_data)
-{
-       return widget_base_class_on_update(instance_h, content, force);
-}
-
-static int __class_on_destroy(widget_base_instance_h instance_h,
-               widget_base_destroy_type_e reason, bundle *content,
-               void *class_data)
-{
-       return widget_base_class_on_destroy(instance_h, reason, content);
-}
-
-static void __multiwindow_instance_create(
-               appcore_multiwindow_base_instance_h instance_h,
-               void *class_data)
-{
-       widget_base_instance_data *instance_data;
-       bundle *b;
-       bundle *content_info = NULL;
-       char *id = NULL;
-       char *class_id = NULL;
-       char *operation = NULL;
-       char *content = NULL;
-       char *w_str = NULL;
-       char *h_str = NULL;
-       char *remain = NULL;
-       int w = 0;
-       int h = 0;
-       int ret = -1;
-       widget_base_class *cls;
-       double *period = NULL;
-       size_t size;
-
-       appcore_multiwindow_base_class_on_create(instance_h);
-       instance_data = appcore_multiwindow_base_instance_get_extra(instance_h);
-       b = instance_data->args;
-
-       bundle_get_str(b, WIDGET_K_CLASS, &class_id);
-       /* for previous version compatibility, use appid for default class id */
-       if (class_id == NULL)
-               class_id = __appid;
-
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-
-       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
-       bundle_get_str(b, WIDGET_K_OPERATION, &operation);
-
-       if (!operation) {
-               LOGE("no operation provided");
-               return;
-       }
-
-       bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
-       bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
-       bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
-
-       if (w_str)
-               w = (int)g_ascii_strtoll(w_str, &remain, 10);
-
-       if (h_str)
-               h = (int)g_ascii_strtoll(h_str, &remain, 10);
-
-       if (content)
-               content_info = bundle_decode((const bundle_raw *)content,
-                               strlen(content));
-
-       if (cls->ops.create)
-               ret = cls->ops.create(instance_h, content_info, w, h, class_data);
-
-       if (ret < 0) {
-               LOGW("Create callback returns error(%d)", ret);
-               ret = __send_update_status(class_id, id,
-                               WIDGET_INSTANCE_EVENT_CREATE_ABORTED, ret, NULL);
-               if (ret < 0)
-                       LOGE("Fail to send abort status (%d) ", ret);
-               __instance_drop(instance_h);
-       } else {
-               LOGD("%s is created", id);
-               aul_widget_instance_add(class_id, id);
-               ret = __send_update_status(class_id, id,
-                       WIDGET_INSTANCE_EVENT_CREATE, 0, NULL);
-               if (ret < 0)
-                       LOGE("Fail to send create status (%d) ", ret);
-
-               ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period,
-                               &size);
-               if (ret == BUNDLE_ERROR_NONE && *period > 0) {
-                       LOGI("set periodic update timer (%lf)", *period);
-                       instance_data->period = *period;
-                       instance_data->periodic_timer = g_timeout_add_seconds(
-                                       instance_data->period,
-                                       __timeout_cb, instance_data);
-               }
-       }
-
-       if (content_info)
-               bundle_free(content_info);
-}
-
-static void __multiwindow_instance_resume(
-               appcore_multiwindow_base_instance_h instance_h,
-               void *class_data)
-{
-       const char *id;
-       const char *class_id;
-       widget_base_class *cls;
-       widget_base_instance_data *data;
-
-       appcore_multiwindow_base_class_on_resume(instance_h);
-       id = appcore_multiwindow_base_instance_get_id(instance_h);
-       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-
-       data = (widget_base_instance_data *)
-                       appcore_multiwindow_base_instance_get_extra(instance_h);
-
-       if (data->pending_update) {
-               LOGD("pending update!");
-               data->pending_update = false;
-               __call_update_cb(class_id, data->id, 0, data->pending_content);
-               if (data->period > 0) {
-                       LOGD("Restart timer!");
-                       data->periodic_timer = g_timeout_add_seconds(
-                                       data->period,
-                                       __timeout_cb, data);
-               }
-       }
-
-       if (cls->ops.resume)
-               cls->ops.resume(instance_h, class_data);
-
-       LOGD("%s is resumed", id);
-       __send_update_status(class_id, id,
-               WIDGET_INSTANCE_EVENT_RESUME, 0, NULL);
-
-       if (!__fg_signal) {
-               LOGD("Send fg signal to resourceD");
-               aul_widget_instance_change_status(class_id, STATUS_FOREGROUND);
-               __fg_signal = true;
-       }
-}
-
-static void __multiwindow_instance_pause(
-               appcore_multiwindow_base_instance_h instance_h,
-               void *class_data)
-{
-       const char *id;
-       const char *class_id;
-       widget_base_class *cls;
-
-       appcore_multiwindow_base_class_on_pause(instance_h);
-       id = appcore_multiwindow_base_instance_get_id(instance_h);
-       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-
-       if (cls->ops.pause)
-               cls->ops.pause(instance_h, class_data);
-
-       LOGD("%s is paused", id);
-       __send_update_status(class_id, id,
-               WIDGET_INSTANCE_EVENT_PAUSE, 0, NULL);
-
-       if (__fg_signal) {
-               LOGD("Send bg signal to resourceD");
-               aul_widget_instance_change_status(class_id, STATUS_BACKGROUND);
-               __fg_signal = false;
-       }
-}
-
-static void __multiwindow_instance_terminate(
-               appcore_multiwindow_base_instance_h instance_h,
-               void *class_data)
-{
-       widget_base_instance_data *data;
-       bundle *b;
-       char *operation = NULL;
-       bundle *content_info;
-       widget_base_destroy_type_e reason = WIDGET_BASE_DESTROY_TYPE_TEMPORARY;
-       int event = WIDGET_INSTANCE_EVENT_TERMINATE;
-       const char *id;
-       const char *class_id;
-       widget_base_class *cls;
-
-       id = appcore_multiwindow_base_instance_get_id(instance_h);
-       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
-       data  = appcore_multiwindow_base_instance_get_extra(
-                       (appcore_multiwindow_base_instance_h)instance_h);
-       b = data->args;
-       cls = __get_class(class_id);
-       if (cls == NULL) {
-               LOGE("class not found: %s", class_id);
-               return;
-       }
-
-       if (b) {
-               bundle_get_str(b, WIDGET_K_OPERATION, &operation);
-               if (operation && strcmp(operation, "destroy") == 0)
-                       reason = WIDGET_BASE_DESTROY_TYPE_PERMANENT;
-       }
-
-       if (data->content)
-               content_info = bundle_decode((const bundle_raw *)data->content,
-                               strlen(data->content));
-       else
-               content_info = bundle_create();
-
-       if (cls->ops.destroy)
-               cls->ops.destroy(instance_h, reason, content_info, class_data);
-
-       LOGW("%s is destroyed %d", id, reason);
-       if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) {
-               __is_permanent = true;
-               event = WIDGET_INSTANCE_EVENT_DESTROY;
-               aul_widget_instance_del(class_id, id);
-       } else {
-               __is_permanent = false;
-               __send_update_status(class_id, id,
-                               WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0,
-                               content_info);
-       }
-
-       if (content_info)
-               bundle_free(content_info);
-
-       if (data->periodic_timer)
-               g_source_remove(data->periodic_timer);
-
-       __send_update_status(class_id, id, event, 0, NULL);
-       appcore_multiwindow_base_class_on_terminate(instance_h);
-}
-
-EXPORT_API int widget_base_class_on_create(widget_base_instance_h instance_h,
-               bundle *content, int w, int h)
-{
-       appcore_multiwindow_base_class_on_create(instance_h);
-
-       return 0;
-}
-
-EXPORT_API int widget_base_class_on_pause(widget_base_instance_h instance_h)
-{
-       appcore_multiwindow_base_class_on_pause(instance_h);
-
-       return 0;
-}
-
-EXPORT_API int widget_base_class_on_resume(widget_base_instance_h instance_h)
-{
-       appcore_multiwindow_base_class_on_resume(instance_h);
-
-       return 0;
-}
-
-EXPORT_API int widget_base_class_on_resize(widget_base_instance_h instance_h,
-               int w, int h)
-{
-       return 0;
-}
-
-EXPORT_API int widget_base_class_on_update(widget_base_instance_h instance_h,
-               bundle *content, int force)
-{
-       return 0;
-}
-
-EXPORT_API int widget_base_class_on_destroy(widget_base_instance_h instance_h,
-               widget_base_destroy_type_e reason, bundle *content)
-{
-       appcore_multiwindow_base_class_on_terminate(instance_h);
-
-       return 0;
-}
-
-EXPORT_API widget_base_class widget_base_class_get_default(void)
-{
-       widget_base_class cls;
-
-       cls.ops.create = __class_on_create;
-       cls.ops.resize = __class_on_resize;
-       cls.ops.update = __class_on_update;
-       cls.ops.destroy = __class_on_destroy;
-       cls.ops.pause = __class_on_pause;
-       cls.ops.resume = __class_on_resume;
-       cls.id = NULL;
-
-       return cls;
-}
-
-EXPORT_API widget_base_class *widget_base_class_add(widget_base_class cls,
-               const char *class_id, void *class_data)
-{
-       widget_base_class *c;
-       appcore_multiwindow_base_class raw_cls;
-
-       if (!__is_widget_feature_enabled()) {
-               LOGE("not supported");
-               set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
-               return NULL;
-       }
-
-       if (!class_id) {
-               LOGE("class id is NULL");
-               set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
-               return NULL;
-       }
-
-       raw_cls.id = strdup(class_id);
-       raw_cls.data = class_data;
-       raw_cls.create = __multiwindow_instance_create;
-       raw_cls.terminate = __multiwindow_instance_terminate;
-       raw_cls.pause = __multiwindow_instance_pause;
-       raw_cls.resume = __multiwindow_instance_resume;
-       appcore_multiwindow_base_class_add(raw_cls);
-
-       c = malloc(sizeof(widget_base_class));
-       if (!c)
-               return NULL;
-
-       *c = cls;
-       c->id = strdup(class_id);
-       __context.classes = g_list_append(__context.classes, c);
-
-       return c;
-}
diff --git a/src/base/widget_base.cc b/src/base/widget_base.cc
new file mode 100644 (file)
index 0000000..45ec082
--- /dev/null
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aul.h>
+#include <aul_app_com.h>
+#include <aul_widget.h>
+#include <bundle_internal.h>
+#include <dlog.h>
+#include <glib.h>
+#include <screen_connector_provider.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <widget_errno.h>
+#include <widget_instance.h>
+
+#include <app_core_multi_window_base.hh>
+
+#include "common/log_private.hh"
+#include "include/widget_base.hh"
+
+namespace tizen_cpp {
+namespace {
+
+constexpr const char kStatusForeground[] = "fg";
+constexpr const char kStatusBackground[] = "bg";
+
+class AppContext {
+ public:
+  void SetAppId(const std::string& app_id) {
+    app_id_ = app_id;
+  }
+
+  const std::string& GetAppId() const {
+    return app_id_;
+  }
+
+  void SetPackageId(const std::string& package_id) {
+    package_id_ = package_id;
+  }
+
+  const std::string& GetPackageId() const {
+    return package_id_;
+  }
+
+  void SetViewerEndpoint(const std::string& viewer_endpoint) {
+    viewer_endpoint_ = viewer_endpoint;
+  }
+
+  const std::string& GetViewerEndpoint() const {
+    return viewer_endpoint_;
+  }
+
+  void SetPermanent(bool permanent) {
+    permanent_ = permanent;
+  }
+
+  bool IsPermanent() const {
+    return permanent_;
+  }
+
+  void SetFgSignal(bool fg_signal) {
+    fg_signal_ = fg_signal;
+  }
+
+  bool IsFgSignal() const {
+    return fg_signal_;
+  }
+
+  int SendUpdateStatus(const std::string& class_id,
+      const std::string& instance_id, int status, int err,
+      bundle* extra) {
+    int ret = aul_widget_send_status_to_viewer(class_id.c_str(),
+        instance_id.c_str(), viewer_endpoint_.c_str(), status, err, extra);
+    if (ret != AUL_R_OK)
+      return ret;
+
+    int lifecycle = widget_instance_convert_event_to_lifecycle_status(status);
+    if (lifecycle > -1) {
+      ret = aul_widget_send_status_to_service(class_id.c_str(),
+          instance_id.c_str(), package_id_.c_str(), lifecycle);
+    }
+
+    return ret;
+  }
+
+ private:
+  std::string app_id_;
+  std::string package_id_;
+  std::string viewer_endpoint_;
+  bool permanent_ = false;
+  bool fg_signal_ = false;
+};
+
+AppContext __context;
+
+}  // namespace
+
+class WidgetBase::Impl {
+ public:
+  explicit Impl(WidgetBase* parent) : parent_(parent) {}
+
+ private:
+  friend class WidgetBase;
+  WidgetBase* parent_;
+
+  void ControlCreate(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlDestroy(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlResume(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlPause(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlChangePeriod(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlUpdate(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void ControlResize(const std::string& class_id, const std::string& id,
+      const tizen_base::Bundle& b);
+  void GetContent(tizen_base::Bundle& b);
+};
+
+WidgetBase* __widget;
+
+class WidgetContext::Impl {
+ public:
+  explicit Impl(WidgetContext* parent) : parent_(parent) {}
+
+  ~Impl() {
+    UnsetPeriodicTimer();
+  }
+
+ private:
+  void UpdateProcess(const tizen_base::Bundle& b);
+  void OnUpdate(bool force);
+  void SetPeriod(double period);
+  void SetPeriodicTimer();
+  void UnsetPeriodicTimer();
+  static gboolean TimedOutCb(gpointer user_data);
+
+ private:
+  friend class WidgetContext;
+  friend class WidgetBase;
+  friend class WidgetBase::Impl;
+
+  WidgetContext* parent_;
+
+  std::unique_ptr<tizen_base::Bundle> args_;
+  std::string content_;
+  double period_;
+  guint periodic_timer_ = 0;
+  bool pending_update_;
+  std::string pending_content_;
+};
+
+void WidgetBase::Impl::ControlCreate(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  if (parent_->FindById(id).get() != nullptr) {
+    _E("Already exists. ID(%s)", id.c_str());
+    return;
+  }
+
+  std::shared_ptr<Context> context;
+  try {
+    context = parent_->CreateContext(class_id, id);
+  } catch (std::runtime_error& e) {
+    _E("runtime_error exception occurs");
+    return;
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  wc->impl_->args_.reset(new tizen_base::Bundle(b));
+  auto ctx = parent_->RunContext(context);
+  if (ctx.get() == nullptr)
+    return;
+
+  wc->impl_->args_.reset();
+  wc->impl_->content_ = b.GetString(WIDGET_K_CONTENT_INFO);
+}
+
+void WidgetBase::Impl::ControlDestroy(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    aul_widget_instance_del(class_id.c_str(), id.c_str());
+    return;
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  wc->impl_->args_.reset(new tizen_base::Bundle(b));
+  parent_->ExitContext(context);
+}
+
+void WidgetBase::Impl::ControlResume(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    return;
+  }
+
+  context->Resume();
+}
+
+void WidgetBase::Impl::ControlPause(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    return;
+  }
+
+  context->Pause();
+}
+
+void WidgetBase::Impl::ControlUpdate(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  if (id.empty()) {
+    for (auto& i : parent_->GetContexts()) {
+      if (i->GetContextId() == class_id) {
+        WidgetContext* cxt = dynamic_cast<WidgetContext*>(i.get());
+        if (cxt == nullptr)
+          continue;
+
+        cxt->impl_->UpdateProcess(b);
+      }
+    }
+    return;
+  }
+
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    return;
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  wc->impl_->UpdateProcess(b);
+}
+
+void WidgetBase::Impl::ControlResize(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    return;
+  }
+
+  int w = 0;
+  std::string w_str = b.GetString(WIDGET_K_WIDTH);
+  if (!w_str.empty()) {
+    char* remain = nullptr;
+    w = static_cast<int>(g_ascii_strtoll(w_str.c_str(), &remain, 10));
+  }
+
+  int h = 0;
+  std::string h_str = b.GetString(WIDGET_K_HEIGHT);
+  if (!h_str.empty()) {
+    char* remain = nullptr;
+    h = static_cast<int>(g_ascii_strtoll(h_str.c_str(), &remain, 10));
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  wc->OnResize(w, h);
+
+  _D("WidgetContext(%s) is resized to %dx%d", id.c_str(), w, h);
+  __context.SendUpdateStatus(class_id, id,
+      WIDGET_INSTANCE_EVENT_SIZE_CHANGED, 0, nullptr);
+}
+
+void WidgetBase::Impl::ControlChangePeriod(const std::string& class_id,
+    const std::string& id, const tizen_base::Bundle& b) {
+  auto context = parent_->FindById(id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", id.c_str());
+    return;
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  wc->impl_->UnsetPeriodicTimer();
+
+  auto v = b.GetByte(WIDGET_K_PERIOD);
+  if (v.empty())
+    return;
+
+  const double* period = reinterpret_cast<double*>(v.data());
+  wc->impl_->SetPeriod(*period);
+  wc->impl_->SetPeriodicTimer();
+}
+
+void WidgetBase::Impl::GetContent(tizen_base::Bundle& b) {
+  std::string instance_id = b.GetString(AUL_K_WIDGET_INSTANCE_ID);
+  if (instance_id.empty()) {
+    _E("Instance ID is nullptr");
+    return;
+  }
+
+  auto context = parent_->FindById(instance_id);
+  if (context.get() == nullptr) {
+    _E("Failed to find widget context. ID(%s)", instance_id.c_str());
+    return;
+  }
+
+  WidgetContext* wc = dynamic_cast<WidgetContext*>(context.get());
+  if (wc == nullptr)
+    return;
+
+  if (!wc->impl_->content_.empty()) {
+    b.Add(AUL_K_WIDGET_CONTENT_INFO, wc->impl_->content_);
+    _D("Content info of %s found", instance_id.c_str());
+  } else {
+    b.Add(AUL_K_WIDGET_CONTENT_INFO, "");
+    _D("Empty content info added");
+  }
+}
+
+WidgetBase::WidgetBase() : impl_(std::make_unique<WidgetBase::Impl>(this)) {
+}
+
+WidgetBase::~WidgetBase() = default;
+
+std::string WidgetBase::GetViewerEndpoint() {
+  return __context.GetViewerEndpoint();
+}
+
+void WidgetBase::Run(int argc, char** argv) {
+  bundle* kb = bundle_import_from_argv(argc, argv);
+  if (kb) {
+    tizen_base::Bundle b(kb, false, true);
+    __context.SetViewerEndpoint(b.GetString(AUL_K_WIDGET_VIEWER));
+    if (!__context.GetViewerEndpoint().empty())
+      _D("Viewer endpoint :%s", __context.GetViewerEndpoint().c_str());
+    else
+      _E("Endpoint is missing");
+  } else {
+    _E("Failed to get launch argv");
+    throw std::runtime_error("Failed to get launch argv");
+  }
+
+  AppCoreMultiWindowBase::Run(argc, argv);
+}
+
+void WidgetBase::Dispose() {
+  AppCoreMultiWindowBase::Dispose();
+  if (getenv("AUL_LOADER_INIT")) {
+      unsetenv("AUL_LOADER_INIT");
+      OnLoopFinish();
+  }
+}
+
+void WidgetBase::ExitContext(
+    std::shared_ptr<AppCoreMultiWindowBase::Context> context) {
+  AppCoreMultiWindowBase::ExitContext(context);
+  int cnt = GetContextCnt();
+  if (cnt == 0)
+    Exit();
+
+  aul_widget_write_log(LOG_TAG,
+      "[%s:%d] instance_id(%s)", __FUNCTION__, __LINE__,
+      context->GetInstId().c_str());
+}
+
+void WidgetBase::Exit() {
+  AppCoreMultiWindowBase::Exit();
+  int cnt = GetContextCnt();
+  int ret = 0;
+  if (cnt == 0 && __context.IsPermanent())
+    ret = aul_notify_exit();
+
+  aul_widget_write_log(LOG_TAG,
+      "[%s:%d] exit : ret(%d), cnt(%d), permanent(%d)",
+      __FUNCTION__, __LINE__, ret, cnt, __context.IsPermanent());
+}
+
+int WidgetBase::OnCreate() {
+  AppCoreMultiWindowBase::OnCreate();
+
+  char appid[256] = { 0, };
+  int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
+  if (ret != AUL_R_OK) {
+    _E("aul_app_get_appid_bypid() is failed. error(%d)", ret);
+    return -1;
+  }
+
+  __context.SetAppId(appid);
+
+  char pkgid[256] = { 0, };
+  ret = aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid));
+  if (ret != AUL_R_OK) {
+    _E("aul_app_get_pkgid_bypid() is failed. error(%d)", ret);
+    return -1;
+  }
+
+  __context.SetPackageId(pkgid);
+
+  screen_connector_provider_init();
+  _D("Widget base is created");
+  __widget = this;
+  return 0;
+}
+
+int WidgetBase::OnTerminate() {
+  screen_connector_provider_fini();
+  __widget = nullptr;
+
+  AppCoreMultiWindowBase::OnTerminate();
+  _D("Widget base is terminated");
+  return 0;
+}
+
+int WidgetBase::OnReceive(aul_type type, tizen_base::Bundle b) {
+  AppCoreMultiWindowBase::OnReceive(type,
+      tizen_base::Bundle(b.GetHandle(), false, false));
+
+  switch (type) {
+    case AUL_RESUME: {
+        for (auto& i : GetContexts())
+          i->Resume();
+      }
+      break;
+    case AUL_TERMINATE:
+      Exit();
+      break;
+    case AUL_WIDGET_CONTENT:
+      impl_->GetContent(b);
+      break;
+    default:
+      break;
+  }
+
+  return 0;
+}
+
+int WidgetBase::OnControl(tizen_base::Bundle b) {
+  AppCoreMultiWindowBase::OnControl(
+      tizen_base::Bundle(b.GetHandle(), false, false));
+
+  std::string class_id = b.GetString(WIDGET_K_CLASS);
+  /* for previous version compatibility, use appid for default class id */
+  if (class_id.empty())
+    class_id = __context.GetAppId();
+
+  std::string id = b.GetString(AUL_K_WIDGET_INSTANCE_ID);
+  std::string operation = b.GetString(WIDGET_K_OPERATION);
+  if (operation.empty()) {
+    _E("Operation is empty");
+    return 0;
+  }
+
+  _I("Operation(%s)", operation.c_str());
+  if (operation == "create")
+    impl_->ControlCreate(class_id, id, b);
+  else if (operation == "resize")
+    impl_->ControlResize(class_id, id, b);
+  else if (operation == "update")
+    impl_->ControlUpdate(class_id, id, b);
+  else if (operation == "destroy")
+    impl_->ControlDestroy(class_id, id, b);
+  else if (operation == "resume")
+    impl_->ControlResume(class_id, id, b);
+  else if (operation == "pause")
+    impl_->ControlPause(class_id, id, b);
+  else if (operation == "terminate")
+    impl_->ControlDestroy(class_id, id, b);
+  else if (operation == "period")
+    impl_->ControlChangePeriod(class_id, id, b);
+
+  return 0;
+}
+
+void WidgetContext::Impl::OnUpdate(bool force) {
+  parent_->OnUpdate(pending_content_.empty() ? tizen_base::Bundle() :
+      tizen_base::Bundle(pending_content_), force);
+
+  std::string class_id = parent_->GetContextId();
+  std::string id = parent_->GetInstId();
+  __context.SendUpdateStatus(class_id, id,
+      WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr);
+  _D("Updated: %s", id.c_str());
+}
+
+void WidgetContext::Impl::UpdateProcess(const tizen_base::Bundle& b) {
+  bool force;
+  std::string force_str = b.GetString(WIDGET_K_FORCE);
+  if (force_str == "true")
+    force = true;
+  else
+    force = false;
+
+  std::string content_raw = b.GetString(WIDGET_K_CONTENT_INFO);
+  if (!parent_->IsResumed() && !force) {
+    pending_content_ = content_raw;
+    pending_update_ = true;
+  } else {
+    parent_->OnUpdate(content_raw.empty() ? tizen_base::Bundle() :
+        tizen_base::Bundle(content_raw), force);
+
+    std::string class_id = parent_->GetContextId();
+    std::string id = parent_->GetInstId();
+    __context.SendUpdateStatus(class_id, id,
+        WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr);
+    _D("Updated: %s", id.c_str());
+  }
+}
+
+void WidgetContext::Impl::SetPeriod(double period) {
+  period_ = period;
+}
+
+void WidgetContext::Impl::SetPeriodicTimer() {
+  if (periodic_timer_)
+    return;
+
+  if (period_ > 0) {
+    _D("Restart timer!");
+    periodic_timer_ = g_timeout_add_seconds(period_,
+        TimedOutCb, parent_);
+  }
+}
+
+void WidgetContext::Impl::UnsetPeriodicTimer() {
+  if (periodic_timer_) {
+    _D("Remove timer!");
+    g_source_remove(periodic_timer_);
+    periodic_timer_ = 0;
+  }
+}
+
+gboolean WidgetContext::Impl::TimedOutCb(gpointer user_data) {
+  WidgetContext* wc = reinterpret_cast<WidgetContext*>(user_data);
+  if (wc->IsResumed()) {
+    _D("Periodic update!");
+    wc->OnUpdate(tizen_base::Bundle(), false);
+
+    __context.SendUpdateStatus(wc->GetContextId(), wc->GetInstId(),
+        WIDGET_INSTANCE_EVENT_UPDATE, 0, nullptr);
+    _D("Updated: %s", wc->GetInstId().c_str());
+  } else {
+    wc->impl_->pending_update_ = true;
+    wc->impl_->UnsetPeriodicTimer();
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+WidgetContext::WidgetContext(std::string context_id, std::string inst_id,
+    AppCoreMultiWindowBase* app)
+    : AppCoreMultiWindowBase::Context(
+          std::move(context_id), std::move(inst_id), app),
+      impl_(std::make_unique<WidgetContext::Impl>(this)) {
+}
+
+WidgetContext::~WidgetContext() = default;
+
+void WidgetContext::OnPause() {
+  std::string id = GetInstId();
+  _D("WidgetContext(%s) is paused", id.c_str());
+  std::string class_id = GetContextId();
+  __context.SendUpdateStatus(class_id.c_str(), id.c_str(),
+      WIDGET_INSTANCE_EVENT_PAUSE, 0, nullptr);
+
+  if (__context.IsFgSignal()) {
+    _D("Send bg signal to resourceD");
+    aul_widget_instance_change_status(class_id.c_str(), kStatusBackground);
+    __context.SetFgSignal(false);
+  }
+}
+
+void WidgetContext::OnResume() {
+  if (impl_->pending_update_) {
+    _D("Pending update!");
+    impl_->pending_update_ = false;
+    impl_->OnUpdate(false);
+    impl_->SetPeriodicTimer();
+  }
+
+  std::string id = GetInstId();
+  _D("WidgetContext(%s) is resumed", id.c_str());
+  std::string class_id = GetContextId();
+  __context.SendUpdateStatus(class_id.c_str(), id.c_str(),
+      WIDGET_INSTANCE_EVENT_RESUME, 0, nullptr);
+
+  if (!__context.IsFgSignal()) {
+    _D("Send fg signal to resourceD");
+    aul_widget_instance_change_status(class_id.c_str(), kStatusForeground);
+    __context.SetFgSignal(true);
+  }
+}
+
+void WidgetContext::OnResize(int w, int h) {
+}
+
+void WidgetContext::OnUpdate(const tizen_base::Bundle& contents, bool force) {
+}
+
+void WidgetContext::ExitAsync() {
+  tizen_base::Bundle b;
+  b.Add(WIDGET_K_OPERATION, "terminate");
+
+  impl_->args_.reset(new tizen_base::Bundle(std::move(b)));
+  g_idle_add([](gpointer user_data) -> gboolean {
+    if (__widget == nullptr)
+      return G_SOURCE_REMOVE;
+
+    WidgetContext* wc = static_cast<WidgetContext*>(user_data);
+
+    std::string id = wc->GetInstId();
+    auto context = __widget->FindById(id);
+    if (context.get() == nullptr) {
+      _E("Failed to find context. ID(%s)", id.c_str());
+      return G_SOURCE_REMOVE;
+    }
+
+    __widget->ExitContext(context);
+    return G_SOURCE_REMOVE;
+  }, this);
+}
+
+int WidgetContext::SetContents(const tizen_base::Bundle& contents) {
+  std::string id = GetInstId();
+  if (id.empty())
+    return WIDGET_ERROR_FAULT;
+
+  std::string class_id = GetContextId();
+  if (class_id.empty())
+    return WIDGET_ERROR_FAULT;
+
+  int ret = __context.SendUpdateStatus(class_id, id,
+      WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, contents.GetHandle());
+  if (ret < 0) {
+    _E("Failed to send content info: %s of %s (%d)",
+        id.c_str(), class_id.c_str(), ret);
+    return WIDGET_ERROR_FAULT;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+int WidgetContext::WindowBind(std::string id, Ecore_Wl2_Window* wl_win) {
+  wl_surface* surface = ecore_wl2_window_surface_get(wl_win);
+  if (surface == nullptr) {
+    _E("Failed to get surface, wl_win(%p)", wl_win);
+    return -1;
+  }
+
+  screen_connector_provider_remote_enable(id.c_str(), surface);
+  WindowBind(wl_win);
+  return 0;
+}
+
+void WidgetContext::OnCreate() {
+  auto& b = impl_->args_;
+  std::string class_id = b->GetString(WIDGET_K_CLASS);
+  /* For previous version compatibility, use appid for default class id */
+  if (class_id.empty())
+    class_id = __context.GetAppId();
+
+  std::string id = b->GetString(AUL_K_WIDGET_INSTANCE_ID);
+  std::string operation = b->GetString(WIDGET_K_OPERATION);
+  if (operation.empty()) {
+    _E("Operation is empty");
+    return;
+  }
+
+  std::string w_str = b->GetString(WIDGET_K_WIDTH);
+  int w = 0;
+  if (!w_str.empty()) {
+    char* remain = nullptr;
+    w = static_cast<int>(g_ascii_strtoll(w_str.c_str(), &remain, 10));
+  }
+
+  std::string h_str = b->GetString(WIDGET_K_HEIGHT);
+  int h = 0;
+  if (!h_str.empty()) {
+    char* remain = nullptr;
+    h = static_cast<int>(g_ascii_strtoll(h_str.c_str(), &remain, 10));
+  }
+
+  tizen_base::Bundle content_info;
+  std::string content = b->GetString(WIDGET_K_CONTENT_INFO);
+  try {
+    if (!content.empty())
+      content_info = tizen_base::Bundle(content);
+  } catch (std::bad_alloc& e) {
+    _W("Failed to decode content info(%s)", content.c_str());
+  }
+
+  bool r = OnCreate(content_info, w, h);
+  if (!r) {
+    _W("Create callback returns error");
+    int ret = __context.SendUpdateStatus(class_id, id,
+        WIDGET_INSTANCE_EVENT_CREATE_ABORTED, WIDGET_ERROR_CANCELED, nullptr);
+    if (ret != 0)
+      _E("Failed to send abrot status. error(%d)", ret);
+
+    throw std::runtime_error("Create callback returns error");
+  } else {
+    _D("WidgetContext(%s) is created", id.c_str());
+    aul_widget_instance_add(class_id.c_str(), id.c_str());
+    int ret = __context.SendUpdateStatus(class_id, id,
+        WIDGET_INSTANCE_EVENT_CREATE, 0, nullptr);
+    if (ret != 0)
+      _E("Failed to send create status. error(%d)", ret);
+
+    auto v = b->GetByte(WIDGET_K_PERIOD);
+    if (v.empty())
+      return;
+
+    const double* period = reinterpret_cast<double*>(v.data());
+    if (*period > 0) {
+      _I("Set periodic update timer. period(%lf)", *period);
+      impl_->SetPeriod(*period);
+      impl_->SetPeriodicTimer();
+    }
+  }
+}
+
+void WidgetContext::OnTerminate() {
+  DestroyType reason = DestroyType::TEMPORARY;
+  int event = WIDGET_INSTANCE_EVENT_TERMINATE;
+  std::string id = GetInstId();
+  std::string class_id = GetContextId();
+  auto& b = impl_->args_;
+  if (b.get()) {
+    std::string operation = b->GetString(WIDGET_K_OPERATION);
+    if (operation == "destroy")
+      reason = DestroyType::PERMANENT;
+  }
+
+  tizen_base::Bundle content_info = impl_->content_.empty() ?
+      tizen_base::Bundle() : tizen_base::Bundle(impl_->content_);
+
+  OnDestroy(reason, content_info);
+
+  _W("WidgetContext(%s) is destroyed. reason(%s)", id.c_str(),
+      reason == DestroyType::TEMPORARY ? "TEMPORARY" : "PERMANENT");
+  if (reason == DestroyType::PERMANENT) {
+    __context.SetPermanent(true);
+    event = WIDGET_INSTANCE_EVENT_DESTROY;
+    aul_widget_instance_del(class_id.c_str(), id.c_str());
+  } else {
+    __context.SetPermanent(false);
+    __context.SendUpdateStatus(class_id.c_str(), id.c_str(),
+        WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, content_info.GetHandle());
+  }
+
+  impl_->UnsetPeriodicTimer();
+
+  __context.SendUpdateStatus(class_id.c_str(), id.c_str(), event, 0, nullptr);
+}
+
+}  // namespace tizen_cpp
diff --git a/src/base/widget_base_legacy.c b/src/base/widget_base_legacy.c
new file mode 100644 (file)
index 0000000..40115b7
--- /dev/null
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Ecore_Wl2.h>
+#include <appcore_multiwindow_base.h>
+#include <aul.h>
+#include <aul_app_com.h>
+#include <aul_widget.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <dlog.h>
+#include <glib-object.h>
+#include <glib.h>
+#include <screen_connector_provider.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <system_info.h>
+#include <unistd.h>
+#include <widget_errno.h>
+#include <widget_instance.h>
+
+#include "common/export_private.hh"
+#include "common/log_private.hh"
+#include "include/widget_base.h"
+
+#define APP_TYPE_WIDGET "widgetapp"
+#define STATUS_FOREGROUND "fg"
+#define STATUS_BACKGROUND "bg"
+
+static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
+       [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
+       [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
+       [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
+       [APP_EVENT_DEVICE_ORIENTATION_CHANGED]
+                       = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
+       [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
+       [APP_EVENT_SUSPENDED_STATE_CHANGED]
+                       = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
+};
+
+struct app_event_info {
+       app_event_type_e type;
+       void *value;
+};
+
+struct app_event_handler {
+       app_event_type_e type;
+       app_event_cb cb;
+       void *data;
+       void *raw;
+};
+
+struct widget_foreach_context {
+       widget_base_instance_cb callback;
+       void *data;
+};
+
+typedef struct _widget_base_context {
+       widget_base_ops ops;
+       void *data;
+       int argc;
+       char **argv;
+       GList *classes;
+} widget_base_context;
+
+typedef struct _widget_base_instance_data {
+       bundle *args;
+       char *id;
+       char *content;
+       void *tag;
+       double period;
+       guint periodic_timer;
+       bool pending_update;
+       char *pending_content;
+       void *user_data;
+} widget_base_instance_data;
+
+static widget_base_context __context;
+static char *__appid;
+static char *__package_id;
+static bool __fg_signal;
+static char *__viewer_endpoint;
+static bool __is_permanent;
+static void __call_update_cb(const char *class_id, const char *id, int force,
+               const char *content_raw);
+
+static gboolean __timeout_cb(gpointer user_data)
+{
+       widget_base_instance_data *data =
+                       (widget_base_instance_data *)user_data;
+       appcore_multiwindow_base_instance_h cxt;
+       const char *class_id;
+
+       cxt = appcore_multiwindow_base_instance_find(data->id);
+
+       if (!cxt) {
+               LOGE("Can't find the instance");
+               return G_SOURCE_REMOVE;
+       }
+
+       if (appcore_multiwindow_base_instance_is_resumed(cxt)) {
+               LOGD("Periodic update!");
+               class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
+               __call_update_cb(class_id, data->id, 0, NULL);
+       } else {
+               data->pending_update = true;
+               if (data->periodic_timer) {
+                       LOGD("Remove timer!");
+                       g_source_remove(data->periodic_timer);
+                       data->periodic_timer = 0;
+               }
+       }
+
+       return G_SOURCE_CONTINUE;
+}
+
+static bool __is_widget_feature_enabled(void)
+{
+       static bool feature = false;
+       static bool retrieved = false;
+       int ret;
+
+       if (retrieved == true)
+               return feature;
+
+       ret = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
+       if (ret != SYSTEM_INFO_ERROR_NONE) {
+               LOGE("failed to get system info"); /* LCOV_EXCL_LINE */
+               return false; /* LCOV_EXCL_LINE */
+       }
+
+       retrieved = true;
+
+       return feature;
+}
+
+static void __check_empty_instance(void)
+{
+       int cnt = appcore_multiwindow_base_instance_get_cnt();
+
+       if (cnt == 0)
+               widget_base_exit();
+}
+
+static void __instance_drop(appcore_multiwindow_base_instance_h instance_h)
+{
+       widget_base_instance_data *data;
+
+       data = appcore_multiwindow_base_instance_get_extra(instance_h);
+       appcore_multiwindow_base_instance_drop(instance_h);
+       free(data->pending_content);
+       free(data->content);
+       free(data->id);
+       free(data);
+       __check_empty_instance();
+}
+
+static gint __comp_class(gconstpointer a, gconstpointer b)
+{
+       const widget_base_class *cls = a;
+
+       return strcmp(cls->id, b);
+}
+
+static widget_base_class *__get_class(const char *class_id)
+{
+       widget_base_class *cls;
+       GList *class_node;
+
+       class_node = g_list_find_custom(__context.classes, class_id,
+                       __comp_class);
+       if (class_node == NULL) {
+               LOGE("empty classes");
+               return NULL;
+       }
+       cls = (widget_base_class *)class_node->data;
+
+       return cls;
+}
+
+static int __send_update_status(const char *class_id, const char *instance_id,
+       int status, int err, bundle *extra)
+{
+       int lifecycle;
+
+       aul_widget_send_status_to_viewer(class_id, instance_id,
+                       __viewer_endpoint, status, err, extra);
+       lifecycle = widget_instance_convert_event_to_lifecycle_status(status);
+       if (lifecycle > -1) {
+               aul_widget_send_status_to_service(
+                               class_id, instance_id, __package_id, lifecycle);
+       }
+
+       return 0;
+}
+
+static void __control_create(const char *class_id, const char *id, bundle *b)
+{
+       widget_base_instance_data *data;
+       char *content = NULL;
+
+       if (appcore_multiwindow_base_instance_find(id)) {
+               LOGE("Already exist id (%s)", id);
+               return;
+       }
+
+       data = (widget_base_instance_data *)
+                       calloc(1, sizeof(widget_base_instance_data));
+       if (!data) {
+               LOGE("Out of memory");
+               return;
+       }
+
+       data->id = strdup(id);
+       data->args = b;
+
+       /* call stub create */
+       appcore_multiwindow_base_instance_run(class_id, id, data);
+       if (appcore_multiwindow_base_instance_find(id)) {
+               data->args = NULL;
+               bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
+               if (content)
+                       data->content = strdup(content);
+       }
+}
+
+static void __control_resume(const char *class_id, const char *id, bundle *b)
+{
+       appcore_multiwindow_base_instance_h cxt;
+
+       cxt = appcore_multiwindow_base_instance_find(id);
+       if (!cxt) {
+               LOGE("context not found: %s", id);
+               return;
+       }
+
+       /* call stub resume */
+       appcore_multiwindow_base_instance_resume(cxt);
+}
+
+static void __control_pause(const char *class_id, const char *id, bundle *b)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+
+       if (!instance_h) {
+               LOGE("instance not found: %s", id);
+               return;
+       }
+
+       /* call stub pause */
+       appcore_multiwindow_base_instance_pause(instance_h);
+}
+
+static void __control_resize(const char *class_id, const char *id, bundle *b)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       char *remain = NULL;
+       char *w_str = NULL;
+       char *h_str = NULL;
+       int w = 0;
+       int h = 0;
+       void *class_data;
+       widget_base_class *cls;
+       const appcore_multiwindow_base_class *raw_cls;
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+       if (!instance_h) {
+               LOGE("context not found: %s", id);
+               return;
+       }
+
+       raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
+       if (!raw_cls)
+               return;
+
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+       class_data = raw_cls->data;
+       bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
+       bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
+
+       if (w_str)
+               w = (int)g_ascii_strtoll(w_str, &remain, 10);
+
+       if (h_str)
+               h = (int)g_ascii_strtoll(h_str, &remain, 10);
+
+       if (cls->ops.resize)
+               cls->ops.resize(instance_h, w, h, class_data);
+
+       LOGD("%s is resized to %dx%d", id, w, h);
+       __send_update_status(class_id, id,
+               WIDGET_INSTANCE_EVENT_SIZE_CHANGED, 0, NULL);
+}
+
+static void __call_update_cb(const char *class_id, const char *id, int force,
+               const char *content_raw)
+{
+       void *class_data;
+       widget_base_class *cls;
+       const appcore_multiwindow_base_class *raw_cls;
+       appcore_multiwindow_base_instance_h instance_h;
+       bundle *content = NULL;
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+       if (!instance_h) {
+               LOGE("context not found: %s", id);
+               return;
+       }
+
+       raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
+       if (!raw_cls) {
+               LOGE("class is NULL");
+               return;
+       }
+
+       class_data = raw_cls->data;
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+
+       if (!cls->ops.update) {
+               LOGE("update callback is NULL");
+               return;
+       }
+
+       if (content_raw) {
+               content = bundle_decode((const bundle_raw *)content_raw,
+                               strlen(content_raw));
+       }
+
+       if (cls->ops.update)
+               cls->ops.update(instance_h, content, force, class_data);
+
+       __send_update_status(class_id, id,
+               WIDGET_INSTANCE_EVENT_UPDATE, 0, NULL);
+       LOGD("updated:%s", id);
+
+       if (content)
+               bundle_free(content);
+}
+
+static void __update_pending_content(
+               appcore_multiwindow_base_instance_h instance_h,
+               const char *content_raw)
+{
+       widget_base_instance_data *data;
+
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       if (data->pending_content) {
+               free(data->pending_content);
+               data->pending_content = NULL;
+       }
+
+       if (content_raw) {
+               data->pending_content = strdup(content_raw);
+               if (data->pending_content == NULL)
+                       LOGW("Out of memory");
+       }
+
+       data->pending_update = true;
+}
+
+static void __update_process(const char *class_id, const char *id,
+               appcore_multiwindow_base_instance_h instance_h, void *data)
+{
+       char *content_raw = NULL;
+       char *force_str = NULL;
+       int force;
+       bundle *b = data;
+
+       if (!b) {
+               LOGE("bundle is NULL");
+               return;
+       }
+
+       bundle_get_str(b, WIDGET_K_FORCE, &force_str);
+
+       if (force_str && strcmp(force_str, "true") == 0)
+               force = 1;
+       else
+               force = 0;
+
+       bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw);
+       if (!appcore_multiwindow_base_instance_is_resumed(instance_h) && !force)
+               __update_pending_content(instance_h, content_raw);
+       else
+               __call_update_cb(class_id, id, force, content_raw);
+}
+
+static void __control_update(const char *class_id, const char *id, bundle *b)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+
+       if (!id) {
+               appcore_multiwindow_base_instance_foreach(class_id,
+                               __update_process, b);
+               return;
+       }
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+       if (!instance_h) {
+               LOGE("context not found: %s", id);
+               return;
+       }
+
+       __update_process(class_id, id, instance_h, b);
+}
+
+static void __control_destroy(const char *class_id, const char *id, bundle *b)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+       if (!instance_h) {
+               LOGE("could not find widget obj: %s, clear amd info", id);
+               aul_widget_instance_del(class_id, id);
+               return;
+       }
+
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+       data->args = b;
+
+       /* call stub terminate */
+       appcore_multiwindow_base_instance_exit(instance_h);
+       free(data->pending_content);
+       free(data->content);
+       free(data->id);
+       free(data);
+       __check_empty_instance();
+       aul_widget_write_log(LOG_TAG,
+               "[%s:%d] instance_id(%s)", __FUNCTION__, __LINE__, id);
+}
+
+static void __control_change_period(const char *class_id, const char *id,
+               bundle *b)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+       double *period = NULL;
+       size_t size;
+       int ret;
+
+       instance_h = appcore_multiwindow_base_instance_find(id);
+       if (!instance_h) {
+               LOGE("context not found: %s", id);
+               return;
+       }
+
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       if (!data) {
+               LOGE("could not find instance data: %s", id);
+               return;
+       }
+
+       if (data->periodic_timer) {
+               LOGD("Remove timer!");
+               g_source_remove(data->periodic_timer);
+               data->periodic_timer = 0;
+       }
+
+       ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size);
+       if (ret == BUNDLE_ERROR_NONE)
+               data->period = *period;
+
+       if (data->period > 0) {
+               LOGD("Restart timer!");
+               data->periodic_timer = g_timeout_add_seconds(data->period,
+                               __timeout_cb, data);
+       }
+
+       return;
+}
+
+static int __multiwindow_create(void *data)
+{
+       char pkgid[256] = {0, };
+       int ret = 0;
+
+       appcore_multiwindow_base_on_create();
+       app_get_id(&__appid);
+       if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
+               __package_id = strdup(pkgid);
+
+       if (!__package_id || !__appid) {
+               LOGE("__package_id is NULL");
+               return -1;
+       }
+
+       screen_connector_provider_init();
+       if (__context.ops.create)
+               ret = __context.ops.create(data);
+
+       LOGD("widget base is created");
+       return ret;
+}
+
+static int __multiwindow_terminate(void *data)
+{
+       if (__context.ops.terminate)
+               __context.ops.terminate(data);
+       screen_connector_provider_fini();
+
+       if (__viewer_endpoint) {
+               free(__viewer_endpoint);
+               __viewer_endpoint = NULL;
+       }
+
+       if (__package_id) {
+               free(__package_id);
+               __package_id = NULL;
+       }
+
+       if (__appid) {
+               free(__appid);
+               __appid = NULL;
+       }
+
+       appcore_multiwindow_base_on_terminate();
+
+       LOGD("widget base is terminated");
+       return 0;
+}
+
+static int __multiwindow_control(bundle *b, void *data)
+{
+       char *class_id = NULL;
+       char *id = NULL;
+       char *operation = NULL;
+
+       appcore_multiwindow_base_on_control(b);
+       bundle_get_str(b, WIDGET_K_CLASS, &class_id);
+       /* for previous version compatibility, use appid for default class id */
+       if (class_id == NULL)
+               class_id = __appid;
+
+       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
+       bundle_get_str(b, WIDGET_K_OPERATION, &operation);
+
+       if (!operation) {
+               LOGE("operation is NULL");
+               return 0;
+       }
+
+       LOGI("app control operation(%s)", operation);
+       if (strcmp(operation, "create") == 0)
+               __control_create(class_id, id, b);
+       else if (strcmp(operation, "resize") == 0)
+               __control_resize(class_id, id, b);
+       else if (strcmp(operation, "update") == 0)
+               __control_update(class_id, id, b);
+       else if (strcmp(operation, "destroy") == 0)
+               __control_destroy(class_id, id, b);
+       else if (strcmp(operation, "resume") == 0)
+               __control_resume(class_id, id, b);
+       else if (strcmp(operation, "pause") == 0)
+               __control_pause(class_id, id, b);
+       else if (strcmp(operation, "terminate") == 0)
+               __control_destroy(class_id, id, b);
+       else if (strcmp(operation, "period") == 0)
+               __control_change_period(class_id, id, b);
+
+       return 0;
+}
+
+static void __inst_resume_cb(const char *class_id, const char *id,
+               appcore_multiwindow_base_instance_h cxt, void *data)
+{
+       __control_resume(class_id, id, data);
+}
+
+static void __get_content(bundle *b)
+{
+       char *instance_id = NULL;
+       appcore_multiwindow_base_instance_h cxt;
+       widget_base_instance_data * we;
+
+       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
+       if (!instance_id) {
+               LOGE("instance id is NULL");
+               return;
+       }
+
+       cxt = appcore_multiwindow_base_instance_find(instance_id);
+       if (!cxt) {
+               LOGE("could not find widget obj: %s", instance_id);
+               return;
+       }
+
+       we = appcore_multiwindow_base_instance_get_extra(cxt);
+       if (!we) {
+               LOGE("widget extra is NULL");
+               return;
+       }
+
+       if (we->content) {
+               bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content);
+               LOGD("content info of %s found", instance_id);
+       } else {
+               bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, "");
+               LOGD("empty content info added");
+       }
+}
+
+static int __multiwindow_receive(aul_type type, bundle *b, void *data)
+{
+       appcore_multiwindow_base_on_receive(type, b);
+
+       switch (type) {
+       case AUL_RESUME:
+               appcore_multiwindow_base_instance_foreach_full(
+                               __inst_resume_cb, b);
+               break;
+       case AUL_TERMINATE:
+               widget_base_exit();
+               break;
+       case AUL_WIDGET_CONTENT:
+               __get_content(b);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void __multiwindow_init(int argc, char **argv, void *data)
+{
+       if (__context.ops.init)
+               __context.ops.init(argc, argv, data);
+}
+
+static void __multiwindow_finish(void)
+{
+       if (__context.ops.finish) {
+               __context.ops.finish();
+               /* Check Loader case */
+               if (getenv("AUL_LOADER_INIT")) {
+                       unsetenv("AUL_LOADER_INIT");
+                       __context.ops.finish();
+               }
+       }
+}
+
+static void __multiwindow_run(void *data)
+{
+       if (__context.ops.run)
+               __context.ops.run(data);
+}
+
+static void __multiwindow_exit(void *data)
+{
+       if (__context.ops.exit)
+               __context.ops.exit(data);
+}
+
+static void __multiwindow_trim_memory(void *data)
+{
+       if (__context.ops.trim_memory)
+               __context.ops.trim_memory(data);
+}
+
+EXPORT_API int widget_base_exit(void)
+{
+       int ret = 0;
+       int cnt;
+
+       appcore_multiwindow_base_exit();
+       cnt = appcore_multiwindow_base_instance_get_cnt();
+       if (cnt == 0 && __is_permanent)
+               ret = aul_notify_exit();
+
+       aul_widget_write_log(LOG_TAG,
+               "[%s:%d] exit : ret(%d), cnt(%d), permanent(%d)",
+                       __FUNCTION__, __LINE__, ret, cnt, __is_permanent);
+
+       return 0;
+}
+
+static gboolean __finish_event_cb(gpointer user_data)
+{
+       appcore_multiwindow_base_instance_h cxt = user_data;
+       bundle *b;
+       const char *id;
+       const char *class_id;
+
+       if (!cxt) {
+               LOGE("user_data is NULL");
+               return FALSE;
+       }
+
+       id = appcore_multiwindow_base_instance_get_id(cxt);
+       class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
+       b = bundle_create();
+
+       if (!b) {
+               LOGE("Out-of-memory");
+               return FALSE;
+       }
+
+       bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
+       __control_destroy(class_id, id, b);
+       bundle_free(b);
+
+       return FALSE;
+}
+
+EXPORT_API int widget_base_terminate_context(widget_base_instance_h context)
+{
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context) {
+               LOGE("context is null");
+               return WIDGET_ERROR_INVALID_PARAMETER;
+       }
+
+       g_idle_add(__finish_event_cb, context);
+
+       return WIDGET_ERROR_NONE;
+}
+
+static void __inst_full_cb(const char *class_id, const char *id,
+               appcore_multiwindow_base_instance_h cxt, void *data)
+{
+       struct widget_foreach_context *foreach_context = data;
+
+       if (!data)
+               return;
+
+       if (foreach_context->callback)
+               foreach_context->callback(cxt, foreach_context->data);
+}
+
+EXPORT_API int widget_base_foreach_context(widget_base_instance_cb cb, void *data)
+{
+       struct widget_foreach_context foreach_context;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!cb) {
+               LOGE("callback is NULL");
+               return WIDGET_ERROR_INVALID_PARAMETER;
+       }
+
+       foreach_context.callback = cb;
+       foreach_context.data = data;
+       appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
+
+       return WIDGET_ERROR_NONE;
+}
+
+static int __event_cb(void *event, void *data)
+{
+       app_event_handler_h handler = data;
+
+       struct app_event_info app_event;
+
+       app_event.type = handler->type;
+       app_event.value = event;
+
+       if (handler->cb)
+               handler->cb(&app_event, handler->data);
+
+       return 0;
+}
+
+EXPORT_API int widget_base_add_event_handler(app_event_handler_h *event_handler,
+                                       app_event_type_e event_type,
+                                       app_event_cb callback,
+                                       void *user_data)
+{
+       int r;
+       bool feature;
+       app_event_handler_h handler;
+
+       r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
+       if (r < 0)
+               return WIDGET_BASE_ERROR_FAULT;
+
+       if (!feature)
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
+
+       if (event_handler == NULL || callback == NULL)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       if (event_type < APP_EVENT_LOW_MEMORY
+           || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
+
+
+       handler = calloc(1, sizeof(struct app_event_handler));
+       if (!handler)
+               return WIDGET_BASE_ERROR_OUT_OF_MEMORY;
+
+       handler->type = event_type;
+       handler->cb = callback;
+       handler->data = user_data;
+       handler->raw = appcore_base_add_event(
+                       __app_event_converter[event_type], __event_cb, handler);
+       *event_handler = handler;
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API int widget_base_remove_event_handler(app_event_handler_h
+                                               event_handler)
+{
+       int r;
+       bool feature;
+       app_event_type_e type;
+
+       r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
+       if (r < 0)
+               return WIDGET_BASE_ERROR_FAULT;
+
+       if (!feature)
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED;
+
+       if (event_handler == NULL)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       type = event_handler->type;
+       if (type < APP_EVENT_LOW_MEMORY ||
+                       type > APP_EVENT_REGION_FORMAT_CHANGED)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       r = appcore_base_remove_event(event_handler->raw);
+       if (r < 0)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       free(event_handler);
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API int widget_base_context_set_content_info(
+               widget_base_instance_h context,
+               bundle *content_info)
+{
+       int ret = 0;
+       bundle_raw *raw = NULL;
+       int len;
+       const char *id;
+       const char *class_id;
+       widget_base_instance_data *data;
+       appcore_multiwindow_base_instance_h instance_h;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context || !content_info)
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       id = appcore_multiwindow_base_instance_get_id(instance_h);
+       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
+       data = appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       if (!class_id || !id || !data)
+               return WIDGET_BASE_ERROR_FAULT;
+
+       ret = __send_update_status(class_id, id,
+                       WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0, content_info);
+
+       if (data->content)
+               free(data->content);
+
+       bundle_encode(content_info, &raw, &len);
+       if (raw)
+               data->content = strdup((const char *)raw);
+       else
+               data->content = NULL;
+
+       free(raw);
+       if (ret < 0) {
+               /* LCOV_EXCL_START */
+               LOGE("failed to send content info: %s of %s (%d)", id,
+                               class_id, ret);
+               return WIDGET_BASE_ERROR_IO_ERROR;
+               /* LCOV_EXCL_STOP */
+       }
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API int widget_base_context_get_tag(widget_base_instance_h context, void **tag)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context || !tag) {
+               LOGE("Invalid parameter");
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+       }
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       if (!data) {
+               LOGE("Invalid parameter");
+               return WIDGET_ERROR_INVALID_PARAMETER;
+       }
+
+       *tag = data->tag;
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API int widget_base_context_set_tag(widget_base_instance_h context, void *tag)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context) {
+               LOGE("Invalid parameter");
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+       }
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+       data->tag = tag;
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API void *widget_base_context_get_user_data(
+               widget_base_instance_h context)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return NULL; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context) {
+               LOGE("Invalid parameter");
+               return NULL;
+       }
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       return data->user_data;
+}
+
+
+EXPORT_API int widget_base_context_set_user_data(
+               widget_base_instance_h context, void *user_data)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+       widget_base_instance_data *data;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       if (!context) {
+               LOGE("Invalid parameter");
+               return WIDGET_BASE_ERROR_INVALID_PARAMETER;
+       }
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+       data->user_data = user_data;
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API int widget_base_context_get_id(widget_base_instance_h context, char **id)
+{
+       appcore_multiwindow_base_instance_h instance_h;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       instance_h = (appcore_multiwindow_base_instance_h)context;
+       *id = (char *)appcore_multiwindow_base_instance_get_id(instance_h);
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+EXPORT_API const char *widget_base_get_viewer_endpoint()
+{
+       return __viewer_endpoint;
+}
+
+EXPORT_API int widget_base_init(widget_base_ops ops, int argc, char **argv,
+               void *data)
+{
+       bundle *kb;
+       char *viewer_endpoint = NULL;
+       appcore_multiwindow_base_ops raw_ops
+                       = appcore_multiwindow_base_get_default_ops();
+
+       __context.ops = ops;
+       __context.argc = argc;
+       __context.argv = argv;
+       __context.data = data;
+
+       /* override methods */
+       raw_ops.base.create = __multiwindow_create;
+       raw_ops.base.control = __multiwindow_control;
+       raw_ops.base.terminate = __multiwindow_terminate;
+       raw_ops.base.receive = __multiwindow_receive;
+       raw_ops.base.init = __multiwindow_init;
+       raw_ops.base.finish = __multiwindow_finish;
+       raw_ops.base.run = __multiwindow_run;
+       raw_ops.base.exit = __multiwindow_exit;
+       raw_ops.base.trim_memory = __multiwindow_trim_memory;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported"); /* LCOV_EXCL_LINE */
+               return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
+       }
+
+       kb = bundle_import_from_argv(argc, argv);
+       if (kb) {
+               bundle_get_str(kb, AUL_K_WIDGET_VIEWER, &viewer_endpoint);
+               if (viewer_endpoint) {
+                       LOGD("viewer endpoint :%s", viewer_endpoint);
+                       __viewer_endpoint = strdup(viewer_endpoint);
+               } else {
+                       LOGE("endpoint is missing");
+               }
+
+               bundle_free(kb);
+       } else {
+               LOGE("failed to get launch argv"); /* LCOV_EXCL_LINE */
+               return WIDGET_ERROR_FAULT;
+       }
+
+       if (appcore_multiwindow_base_init(raw_ops, argc, argv, data) < 0)
+              return WIDGET_ERROR_FAULT;
+
+       return WIDGET_ERROR_NONE;
+}
+
+static int __on_create(void *data)
+{
+       return widget_base_on_create();
+}
+
+static int __on_terminate(void *data)
+{
+       return widget_base_on_terminate();
+}
+
+static void __on_init(int argc, char **argv, void *data)
+{
+       widget_base_on_init(argc, argv);
+}
+
+static void __on_finish(void)
+{
+       widget_base_on_finish();
+}
+
+static void __on_run(void *data)
+{
+       widget_base_on_run();
+}
+
+static void __on_exit(void *data)
+{
+       widget_base_on_exit();
+}
+
+static void __on_trim_memory(void *data)
+{
+       widget_base_on_trim_memory();
+}
+
+EXPORT_API int widget_base_on_create(void)
+{
+       appcore_multiwindow_base_on_create();
+
+       return 0;
+}
+
+EXPORT_API int widget_base_on_terminate(void)
+{
+       appcore_multiwindow_base_on_terminate();
+
+       return 0;
+}
+
+EXPORT_API int widget_base_on_init(int argc, char **argv)
+{
+       return 0;
+}
+
+EXPORT_API void widget_base_on_finish(void)
+{
+}
+
+EXPORT_API void widget_base_on_run(void)
+{
+}
+
+EXPORT_API void widget_base_on_exit(void)
+{
+}
+
+EXPORT_API int widget_base_on_trim_memory(void)
+{
+       appcore_multiwindow_base_on_trim_memory();
+
+       return 0;
+}
+
+EXPORT_API widget_base_ops widget_base_get_default_ops(void)
+{
+       widget_base_ops ops;
+
+       /* override methods */
+       ops.create = __on_create;
+       ops.terminate = __on_terminate;
+       ops.init = __on_init;
+       ops.finish = __on_finish;
+       ops.run = __on_run;
+       ops.exit = __on_exit;
+       ops.trim_memory = __on_trim_memory;
+
+       return ops;
+}
+
+static void __free_class(gpointer data)
+{
+       widget_base_class *cls = data;
+
+       free(cls->id);
+       free(cls);
+}
+
+EXPORT_API void widget_base_fini(void)
+{
+       appcore_multiwindow_base_fini();
+       g_list_free_full(__context.classes, __free_class);
+       __context.classes = NULL;
+}
+
+EXPORT_API int widget_base_context_window_bind(
+               widget_base_instance_h instance_h, const char *id,
+               Ecore_Wl2_Window *wl_win)
+{
+       struct wl_surface *surface;
+
+       surface = ecore_wl2_window_surface_get(wl_win);
+       if (surface == NULL) {
+               LOGE("failed to get surface"); /* LCOV_EXCL_LINE */
+               return WIDGET_BASE_ERROR_FAULT; /* LCOV_EXCL_LINE */
+       }
+
+       screen_connector_provider_remote_enable(id, surface);
+       appcore_multiwindow_base_window_bind(instance_h, wl_win);
+
+       return WIDGET_BASE_ERROR_NONE;
+}
+
+static int __class_on_create(widget_base_instance_h instance_h, bundle *content,
+               int w, int h, void *class_data)
+{
+       return widget_base_class_on_create(instance_h, content, w, h);
+}
+
+static int __class_on_resume(widget_base_instance_h instance_h,        void *class_data)
+{
+       return widget_base_class_on_resume(instance_h);
+}
+
+static int __class_on_pause(widget_base_instance_h instance_h,
+               void *class_data)
+{
+       return widget_base_class_on_pause(instance_h);
+}
+
+static int __class_on_resize(widget_base_instance_h instance_h, int w, int h,
+               void *class_data)
+{
+       return widget_base_class_on_resize(instance_h, w, h);
+}
+
+static int __class_on_update(widget_base_instance_h instance_h, bundle *content,
+               int force, void *class_data)
+{
+       return widget_base_class_on_update(instance_h, content, force);
+}
+
+static int __class_on_destroy(widget_base_instance_h instance_h,
+               widget_base_destroy_type_e reason, bundle *content,
+               void *class_data)
+{
+       return widget_base_class_on_destroy(instance_h, reason, content);
+}
+
+static void __multiwindow_instance_create(
+               appcore_multiwindow_base_instance_h instance_h,
+               void *class_data)
+{
+       widget_base_instance_data *instance_data;
+       bundle *b;
+       bundle *content_info = NULL;
+       char *id = NULL;
+       char *class_id = NULL;
+       char *operation = NULL;
+       char *content = NULL;
+       char *w_str = NULL;
+       char *h_str = NULL;
+       char *remain = NULL;
+       int w = 0;
+       int h = 0;
+       int ret = -1;
+       widget_base_class *cls;
+       double *period = NULL;
+       size_t size;
+
+       appcore_multiwindow_base_class_on_create(instance_h);
+       instance_data = appcore_multiwindow_base_instance_get_extra(instance_h);
+       b = instance_data->args;
+
+       bundle_get_str(b, WIDGET_K_CLASS, &class_id);
+       /* for previous version compatibility, use appid for default class id */
+       if (class_id == NULL)
+               class_id = __appid;
+
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+
+       bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
+       bundle_get_str(b, WIDGET_K_OPERATION, &operation);
+
+       if (!operation) {
+               LOGE("no operation provided");
+               return;
+       }
+
+       bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
+       bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
+       bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
+
+       if (w_str)
+               w = (int)g_ascii_strtoll(w_str, &remain, 10);
+
+       if (h_str)
+               h = (int)g_ascii_strtoll(h_str, &remain, 10);
+
+       if (content)
+               content_info = bundle_decode((const bundle_raw *)content,
+                               strlen(content));
+
+       if (cls->ops.create)
+               ret = cls->ops.create(instance_h, content_info, w, h, class_data);
+
+       if (ret < 0) {
+               LOGW("Create callback returns error(%d)", ret);
+               ret = __send_update_status(class_id, id,
+                               WIDGET_INSTANCE_EVENT_CREATE_ABORTED, ret, NULL);
+               if (ret < 0)
+                       LOGE("Fail to send abort status (%d) ", ret);
+               __instance_drop(instance_h);
+       } else {
+               LOGD("%s is created", id);
+               aul_widget_instance_add(class_id, id);
+               ret = __send_update_status(class_id, id,
+                       WIDGET_INSTANCE_EVENT_CREATE, 0, NULL);
+               if (ret < 0)
+                       LOGE("Fail to send create status (%d) ", ret);
+
+               ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period,
+                               &size);
+               if (ret == BUNDLE_ERROR_NONE && *period > 0) {
+                       LOGI("set periodic update timer (%lf)", *period);
+                       instance_data->period = *period;
+                       instance_data->periodic_timer = g_timeout_add_seconds(
+                                       instance_data->period,
+                                       __timeout_cb, instance_data);
+               }
+       }
+
+       if (content_info)
+               bundle_free(content_info);
+}
+
+static void __multiwindow_instance_resume(
+               appcore_multiwindow_base_instance_h instance_h,
+               void *class_data)
+{
+       const char *id;
+       const char *class_id;
+       widget_base_class *cls;
+       widget_base_instance_data *data;
+
+       appcore_multiwindow_base_class_on_resume(instance_h);
+       id = appcore_multiwindow_base_instance_get_id(instance_h);
+       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+
+       data = (widget_base_instance_data *)
+                       appcore_multiwindow_base_instance_get_extra(instance_h);
+
+       if (data->pending_update) {
+               LOGD("pending update!");
+               data->pending_update = false;
+               __call_update_cb(class_id, data->id, 0, data->pending_content);
+               if (data->period > 0) {
+                       LOGD("Restart timer!");
+                       data->periodic_timer = g_timeout_add_seconds(
+                                       data->period,
+                                       __timeout_cb, data);
+               }
+       }
+
+       if (cls->ops.resume)
+               cls->ops.resume(instance_h, class_data);
+
+       LOGD("%s is resumed", id);
+       __send_update_status(class_id, id,
+               WIDGET_INSTANCE_EVENT_RESUME, 0, NULL);
+
+       if (!__fg_signal) {
+               LOGD("Send fg signal to resourceD");
+               aul_widget_instance_change_status(class_id, STATUS_FOREGROUND);
+               __fg_signal = true;
+       }
+}
+
+static void __multiwindow_instance_pause(
+               appcore_multiwindow_base_instance_h instance_h,
+               void *class_data)
+{
+       const char *id;
+       const char *class_id;
+       widget_base_class *cls;
+
+       appcore_multiwindow_base_class_on_pause(instance_h);
+       id = appcore_multiwindow_base_instance_get_id(instance_h);
+       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+
+       if (cls->ops.pause)
+               cls->ops.pause(instance_h, class_data);
+
+       LOGD("%s is paused", id);
+       __send_update_status(class_id, id,
+               WIDGET_INSTANCE_EVENT_PAUSE, 0, NULL);
+
+       if (__fg_signal) {
+               LOGD("Send bg signal to resourceD");
+               aul_widget_instance_change_status(class_id, STATUS_BACKGROUND);
+               __fg_signal = false;
+       }
+}
+
+static void __multiwindow_instance_terminate(
+               appcore_multiwindow_base_instance_h instance_h,
+               void *class_data)
+{
+       widget_base_instance_data *data;
+       bundle *b;
+       char *operation = NULL;
+       bundle *content_info;
+       widget_base_destroy_type_e reason = WIDGET_BASE_DESTROY_TYPE_TEMPORARY;
+       int event = WIDGET_INSTANCE_EVENT_TERMINATE;
+       const char *id;
+       const char *class_id;
+       widget_base_class *cls;
+
+       id = appcore_multiwindow_base_instance_get_id(instance_h);
+       class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
+       data  = appcore_multiwindow_base_instance_get_extra(
+                       (appcore_multiwindow_base_instance_h)instance_h);
+       b = data->args;
+       cls = __get_class(class_id);
+       if (cls == NULL) {
+               LOGE("class not found: %s", class_id);
+               return;
+       }
+
+       if (b) {
+               bundle_get_str(b, WIDGET_K_OPERATION, &operation);
+               if (operation && strcmp(operation, "destroy") == 0)
+                       reason = WIDGET_BASE_DESTROY_TYPE_PERMANENT;
+       }
+
+       if (data->content)
+               content_info = bundle_decode((const bundle_raw *)data->content,
+                               strlen(data->content));
+       else
+               content_info = bundle_create();
+
+       if (cls->ops.destroy)
+               cls->ops.destroy(instance_h, reason, content_info, class_data);
+
+       LOGW("%s is destroyed %d", id, reason);
+       if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) {
+               __is_permanent = true;
+               event = WIDGET_INSTANCE_EVENT_DESTROY;
+               aul_widget_instance_del(class_id, id);
+       } else {
+               __is_permanent = false;
+               __send_update_status(class_id, id,
+                               WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, 0,
+                               content_info);
+       }
+
+       if (content_info)
+               bundle_free(content_info);
+
+       if (data->periodic_timer)
+               g_source_remove(data->periodic_timer);
+
+       __send_update_status(class_id, id, event, 0, NULL);
+       appcore_multiwindow_base_class_on_terminate(instance_h);
+}
+
+EXPORT_API int widget_base_class_on_create(widget_base_instance_h instance_h,
+               bundle *content, int w, int h)
+{
+       appcore_multiwindow_base_class_on_create(instance_h);
+
+       return 0;
+}
+
+EXPORT_API int widget_base_class_on_pause(widget_base_instance_h instance_h)
+{
+       appcore_multiwindow_base_class_on_pause(instance_h);
+
+       return 0;
+}
+
+EXPORT_API int widget_base_class_on_resume(widget_base_instance_h instance_h)
+{
+       appcore_multiwindow_base_class_on_resume(instance_h);
+
+       return 0;
+}
+
+EXPORT_API int widget_base_class_on_resize(widget_base_instance_h instance_h,
+               int w, int h)
+{
+       return 0;
+}
+
+EXPORT_API int widget_base_class_on_update(widget_base_instance_h instance_h,
+               bundle *content, int force)
+{
+       return 0;
+}
+
+EXPORT_API int widget_base_class_on_destroy(widget_base_instance_h instance_h,
+               widget_base_destroy_type_e reason, bundle *content)
+{
+       appcore_multiwindow_base_class_on_terminate(instance_h);
+
+       return 0;
+}
+
+EXPORT_API widget_base_class widget_base_class_get_default(void)
+{
+       widget_base_class cls;
+
+       cls.ops.create = __class_on_create;
+       cls.ops.resize = __class_on_resize;
+       cls.ops.update = __class_on_update;
+       cls.ops.destroy = __class_on_destroy;
+       cls.ops.pause = __class_on_pause;
+       cls.ops.resume = __class_on_resume;
+       cls.id = NULL;
+
+       return cls;
+}
+
+EXPORT_API widget_base_class *widget_base_class_add(widget_base_class cls,
+               const char *class_id, void *class_data)
+{
+       widget_base_class *c;
+       appcore_multiwindow_base_class raw_cls;
+
+       if (!__is_widget_feature_enabled()) {
+               LOGE("not supported");
+               set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
+               return NULL;
+       }
+
+       if (!class_id) {
+               LOGE("class id is NULL");
+               set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+               return NULL;
+       }
+
+       raw_cls.id = strdup(class_id);
+       raw_cls.data = class_data;
+       raw_cls.create = __multiwindow_instance_create;
+       raw_cls.terminate = __multiwindow_instance_terminate;
+       raw_cls.pause = __multiwindow_instance_pause;
+       raw_cls.resume = __multiwindow_instance_resume;
+       appcore_multiwindow_base_class_add(raw_cls);
+
+       c = malloc(sizeof(widget_base_class));
+       if (!c)
+               return NULL;
+
+       *c = cls;
+       c->id = strdup(class_id);
+       __context.classes = g_list_append(__context.classes, c);
+
+       return c;
+}
diff --git a/src/common/export_private.hh b/src/common/export_private.hh
new file mode 100644 (file)
index 0000000..1102d02
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMMON_EXPORT_PRIVATE_HH_
+#define COMMON_EXPORT_PRIVATE_HH_
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__ ((visibility("default")))
+
+#undef API
+#define API extern "C" EXPORT_API
+
+#endif  // COMMON_EXPORT_PRIVATE_HH_
diff --git a/src/common/log_private.hh b/src/common/log_private.hh
new file mode 100644 (file)
index 0000000..52b17e6
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMMON_LOG_PRIVATE_HH_
+#define COMMON_LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "CAPI_WIDGET_APPLICATION"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif  // COMMON_LOG_PRIVATE_HH_
index 610bb009ea927b8b15736cc3a6cd462e0673944d..357f9cc3a43833386248c645b52221df6a9b87ae 100644 (file)
@@ -1,25 +1,38 @@
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} WIDGET_APPLICATION_SRCS)
 
 ADD_LIBRARY(${TARGET_WIDGET_APPLICATION} SHARED ${WIDGET_APPLICATION_SRCS})
-SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} PROPERTIES SOVERSION ${MAJORVER})
-SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION} PROPERTIES VERSION ${FULLVER})
-TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION} PRIVATE ${TARGET_WIDGET_BASE})
 
-TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
-TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include/)
+SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION}
+  PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION}
+  PROPERTIES VERSION ${FULLVER})
+TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION}
+  PRIVATE ${TARGET_WIDGET_BASE})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../base/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../common/)
 
 APPLY_PKG_CONFIG(${TARGET_WIDGET_APPLICATION} PUBLIC
   AUL_DEP
   DLOG_DEPS
   APPCORE_COMMON_DEPS
   ELEMENTARY_DEP
+  SYSTEM_INFO_DEPS
   WIDGET_SERVICE_DEPS
   CAPI_APP_COMMON_DEP
 )
 
-CONFIGURE_FILE(../../capi-appfw-widget-application.pc.in ../../capi-appfw-widget-application.pc @ONLY)
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/capi-appfw-widget-application.pc.in
+  ${CMAKE_CURRENT_SOURCE_DIR}/capi-appfw-widget-application.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/capi-appfw-widget-application.pc
+  DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
 INSTALL(TARGETS ${TARGET_WIDGET_APPLICATION} DESTINATION ${LIB_INSTALL_DIR})
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../capi-appfw-widget-application.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw/
        FILES_MATCHING
        PATTERN "*.h*"
diff --git a/src/efl_base/capi-appfw-widget-application.pc.in b/src/efl_base/capi-appfw-widget-application.pc.in
new file mode 100644 (file)
index 0000000..6f7ec01
--- /dev/null
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDEDIR@
+
+Name: capi-appfw-widget-application
+Description: widget application library
+Version: @VERSION@
+Requires.private: aul dlog elementary capi-appfw-app-common widget_service
+Requires: appcore-widget-base
+Libs: -L${libdir} -lcapi-appfw-widget-application
+Cflags: -I${includedir} -I${includedir}/appfw
diff --git a/src/efl_base/widget-log.h b/src/efl_base/widget-log.h
deleted file mode 100644 (file)
index a316028..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef __APPFW_WIDGET_LOG_H__
-#define __APPFW_WIDGET_LOG_H__
-
-#include <dlog.h>
-
-#define _E(fmt, arg...) LOGE(fmt, ##arg)
-#define _I(fmt, arg...) LOGI(fmt, ##arg)
-#define _D(fmt, arg...) LOGD(fmt, ##arg)
-#define _W(fmt, arg...) LOGW(fmt, ##arg)
-
-#ifndef EXPORT_API
-#define EXPORT_API __attribute__ ((visibility("default")))
-#endif
-
-#ifndef _E
-#define _E(fmt, arg...) LOGE(fmt, ##arg)
-#endif
-
-#ifndef _I
-#define _I(...) LOGI(__VA_ARGS__)
-#endif
-
-#ifndef _D
-#define _D(...) LOGD(__VA_ARGS__)
-#endif
-
-#ifndef _W
-#define _W(...) LOGW(__VA_ARGS__)
-#endif
-
-#define _warn_if(expr, fmt, arg...)            \
-       do {                                    \
-               if (expr)                       \
-                       _ERR(fmt, ##arg);       \
-       } while (0)
-
-#define _ret_if(expr)                          \
-       do {                                    \
-               if (expr)                       \
-                       return;                 \
-       } while (0)
-
-#define _retv_if(expr, val)                    \
-       do {                                    \
-               if (expr)                       \
-                       return (val);           \
-       } while (0)
-
-#define _retm_if(expr, fmt, arg...)            \
-       do {                                    \
-               if (expr) {                     \
-                       _ERR(fmt, ##arg);       \
-                       return;                 \
-               }                               \
-       } while (0)
-
-#define _retvm_if(expr, val, fmt, arg...)      \
-       do {                                    \
-               if (expr) {                     \
-                       _ERR(fmt, ##arg);       \
-                       return (val);           \
-               }                               \
-       } while (0)
-
-#endif /* __APPFW_WIDGET_LOG_H_ */
-
diff --git a/src/efl_base/widget-private.h b/src/efl_base/widget-private.h
deleted file mode 100644 (file)
index 34fdc5f..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef __APPCORE_WIDGET_PRIVATE_H__
-#define __APPCORE_WIDGET_PRIVATE_H__
-
-#include <glib.h>
-
-#include <Elementary.h>
-#include <widget_app.h>
-#include <app_common.h>
-#include <widget_errno.h>
-
-int widget_app_error(widget_error_e error, const char *function,
-               const char *description);
-
-#endif /* __APPCORE_WIDGET_PRIVATE_H__ */
-
diff --git a/src/efl_base/widget_app.c b/src/efl_base/widget_app.c
deleted file mode 100644 (file)
index 174195f..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <stdlib.h>
-#include <glib.h>
-
-#include <bundle.h>
-#include <aul.h>
-#include <aul_widget.h>
-#include <dlog.h>
-#include <Elementary.h>
-#include <widget_errno.h>
-#include <widget_instance.h>
-
-#include "widget_base.h"
-#include "widget_app.h"
-#include "widget-log.h"
-#include "widget-private.h"
-#include "widget_app_internal.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_WIDGET_APPLICATION"
-#define ICONIFY_TIMEOUT 500
-
-struct instance_data {
-       Evas_Object *win;
-       guint iconify_timer;
-       bool is_iconified;
-};
-
-struct app_cb_info {
-       widget_app_lifecycle_callback_s *callback;
-       void *user_data;
-};
-
-struct app_class_cb_info {
-       widget_instance_lifecycle_callback_s callback;
-       void *user_data;
-};
-
-static GList *__class_data_list;
-
-static int __class_resize(widget_base_instance_h instance_h, int w, int h,
-               void *class_data)
-{
-       int ret = 0;
-       struct instance_data *data;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-
-       widget_base_class_on_resize(instance_h, w, h);
-       data = (struct instance_data *)
-                       widget_base_context_get_user_data(instance_h);
-
-       if (!data) {
-               _E("widget_base_context_get_user_data() returns null");
-
-               return -1;
-       }
-
-       if (data->win)
-               evas_object_resize(data->win, w, h);
-       else
-               _E("unable to find window");
-
-       if (callback_data && callback_data->callback.resize) {
-               ret = callback_data->callback.resize(
-                               (widget_context_h)instance_h,
-                               w, h, callback_data->user_data);
-       }
-
-       return ret;
-}
-
-static int __class_update(widget_base_instance_h instance_h, bundle *content,
-               int force, void *class_data)
-{
-       int ret = 0;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-
-       widget_base_class_on_update(instance_h, content, force);
-       if (callback_data && callback_data->callback.update) {
-               ret = callback_data->callback.update(
-                               (widget_context_h)instance_h,
-                               content, force, callback_data->user_data);
-       }
-
-       return ret;
-}
-
-static int __class_create(widget_base_instance_h instance_h, bundle *content,
-               int w, int h, void *class_data)
-{
-       int ret = -1;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-
-       widget_base_class_on_create(instance_h, content, w, h);
-       if (callback_data && callback_data->callback.create) {
-               ret = callback_data->callback.create(
-                               (widget_context_h)instance_h,
-                               content, w, h, callback_data->user_data);
-               aul_widget_write_log(LOG_TAG, "[%s:%d]  ret : %d",
-                       __FUNCTION__, __LINE__, ret);
-       }
-       return ret;
-}
-
-static int __class_destroy(widget_base_instance_h instance_h,
-               widget_base_destroy_type_e reason, bundle *content,
-               void *class_data)
-{
-       int ret = 0;
-       struct instance_data *data;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-
-       if (callback_data && callback_data->callback.destroy) {
-               ret = callback_data->callback.destroy(
-                               (widget_context_h)instance_h,
-                               reason, content, callback_data->user_data);
-               aul_widget_write_log(LOG_TAG, "[%s:%d]  ret : %d",
-                       __FUNCTION__, __LINE__, ret);
-       }
-
-       data = (struct instance_data *)widget_base_context_get_user_data(instance_h);
-       if (data != NULL) {
-               widget_base_context_set_user_data(instance_h, NULL);
-               if (data->iconify_timer > 0)
-                       g_source_remove(data->iconify_timer);
-               free(data);
-       }
-
-       widget_base_class_on_destroy(instance_h, reason, content);
-
-       return ret;
-}
-
-static gboolean __iconify_timeout_cb(gpointer user_data)
-{
-       struct instance_data *data = user_data;
-       Ecore_Wl2_Window *win = ecore_evas_wayland2_window_get(
-                       ecore_evas_ecore_evas_get(evas_object_evas_get(data->win)));
-
-       if (win) {
-               ecore_wl2_window_iconified_set(win, EINA_TRUE);
-               data->is_iconified = true;
-               _D("set iconify true");
-       }
-
-       data->iconify_timer = 0;
-
-       return G_SOURCE_REMOVE;
-}
-
-static int __class_pause(widget_base_instance_h instance_h, void *class_data)
-{
-       int ret = 0;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-       struct instance_data *data = (struct instance_data *)
-                       widget_base_context_get_user_data(instance_h);
-
-       if (data->iconify_timer > 0)
-               g_source_remove(data->iconify_timer);
-
-       data->iconify_timer = g_timeout_add(ICONIFY_TIMEOUT,
-                       __iconify_timeout_cb, data);
-
-       widget_base_class_on_pause(instance_h);
-       if (callback_data && callback_data->callback.pause) {
-               ret = callback_data->callback.pause(
-                               (widget_context_h)instance_h,
-                               callback_data->user_data);
-       }
-
-       return ret;
-}
-
-static int __class_resume(widget_base_instance_h instance_h, void *class_data)
-{
-       int ret = 0;
-       struct app_class_cb_info *callback_data =
-                       (struct app_class_cb_info *)class_data;
-       Ecore_Wl2_Window *win;
-       struct instance_data *data = (struct instance_data *)
-                       widget_base_context_get_user_data(instance_h);
-
-       if (data->iconify_timer > 0) {
-               g_source_remove(data->iconify_timer);
-               data->iconify_timer = 0;
-       }
-
-       if (data->is_iconified) {
-               win = ecore_evas_wayland2_window_get(
-                       ecore_evas_ecore_evas_get(evas_object_evas_get(data->win)));
-               if (win) {
-                       ecore_wl2_window_iconified_set(win, EINA_FALSE);
-                       data->is_iconified = false;
-                       _D("set iconify false");
-               }
-       }
-
-       widget_base_class_on_resume(instance_h);
-       if (callback_data && callback_data->callback.resume) {
-               ret = callback_data->callback.resume(
-                               (widget_context_h)instance_h,
-                               callback_data->user_data);
-       }
-
-       return ret;
-}
-
-static int __widget_app_create(void *data)
-{
-       struct app_cb_info *cb_info = (struct app_cb_info *)data;
-       widget_app_lifecycle_callback_s *callback;
-
-       widget_base_on_create();
-       if (cb_info && cb_info->callback && cb_info->callback->create) {
-               callback = cb_info->callback;
-               if (callback->create(cb_info->user_data) == NULL) {
-                       _D("fail to create widget");
-                       return -1;
-               }
-               _D("widget app is created");
-               aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
-               return 0;
-       }
-
-       return -1;
-}
-
-static int __widget_app_terminate(void *data)
-{
-       struct app_cb_info *cb_info = (struct app_cb_info *)data;
-       widget_app_lifecycle_callback_s *callback;
-
-       if (cb_info && cb_info->callback && cb_info->callback->terminate) {
-               callback = cb_info->callback;
-               callback->terminate(cb_info->user_data);
-               widget_base_on_terminate();
-               _D("widget app is terminated");
-               aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
-               return 0;
-       }
-
-       widget_base_on_terminate();
-
-       return -1;
-}
-
-static void __widget_app_init(int argc, char **argv, void *data)
-{
-       elm_init(argc, argv);
-}
-
-static void __widget_app_finish(void)
-{
-       elm_shutdown();
-}
-
-static void __widget_app_run(void *data)
-{
-       elm_run();
-}
-
-static void __widget_app_exit(void *data)
-{
-       elm_exit();
-}
-
-static void __widget_app_trim_memory(void *data)
-{
-       _D("Trim memory");
-       elm_cache_all_flush();
-       widget_base_on_trim_memory();
-}
-
-EXPORT_API int widget_app_main(int argc, char **argv,
-               widget_app_lifecycle_callback_s *callback, void *user_data)
-{
-       widget_base_ops ops;
-       struct app_cb_info cb_info;
-       int r;
-
-       if (argc <= 0 || argv == NULL || callback == NULL)
-               return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
-                               __FUNCTION__, NULL);
-
-       if (callback->create == NULL)
-               return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
-                               __FUNCTION__,
-                               "widget_app_create_cb() callback must be "
-                               "registered");
-
-       ops.create = __widget_app_create;
-       ops.terminate = __widget_app_terminate;
-       ops.init = __widget_app_init;
-       ops.finish = __widget_app_finish;
-       ops.run = __widget_app_run;
-       ops.exit = __widget_app_exit;
-       ops.trim_memory = __widget_app_trim_memory;
-
-       cb_info.callback = callback;
-       cb_info.user_data = user_data;
-
-       r = widget_base_init(ops, argc, argv, &cb_info);
-       widget_base_fini();
-
-       if (__class_data_list) {
-               g_list_free_full(__class_data_list, free);
-               __class_data_list = NULL;
-       }
-
-       return r;
-}
-
-EXPORT_API int widget_app_exit(void)
-{
-       return widget_base_exit();
-}
-
-EXPORT_API int widget_app_terminate_context(widget_context_h context)
-{
-       return widget_base_terminate_context((widget_base_instance_h)context);
-}
-
-EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data)
-{
-       return widget_base_foreach_context((widget_base_instance_cb)cb, data);
-}
-
-EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler,
-                                       app_event_type_e event_type,
-                                       app_event_cb callback,
-                                       void *user_data)
-{
-       return widget_base_add_event_handler(event_handler, event_type,
-                                       callback, user_data);
-}
-
-EXPORT_API int widget_app_remove_event_handler(app_event_handler_h
-                                               event_handler)
-{
-       return widget_base_remove_event_handler(event_handler);
-}
-
-EXPORT_API const char *widget_app_get_id(widget_context_h context)
-{
-       int ret;
-       char *id;
-
-       if (!context) {
-               set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
-               return NULL;
-       }
-
-       ret = widget_base_context_get_id((widget_base_instance_h)context, &id);
-       if (ret != WIDGET_BASE_ERROR_NONE) {
-               _E("failed to get context id"); /* LCOV_EXCL_LINE */
-               set_last_result(ret); /* LCOV_EXCL_LINE */
-               return NULL; /* LCOV_EXCL_LINE */
-       }
-
-       set_last_result(WIDGET_ERROR_NONE);
-       return id;
-}
-
-static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
-{
-       char *plug_id;
-       plug_id = evas_object_data_del(obj, "___PLUGID");
-       free(plug_id);
-}
-
-EXPORT_API int widget_app_get_elm_win(widget_context_h context,
-                                       Evas_Object **win)
-{
-       Evas_Object *ret_win = NULL;
-       Ecore_Wl2_Window *wl_win;
-       struct instance_data *data;
-       char buffer[256];
-       int rots[3] = {0};
-       int win_id;
-       char *id;
-       int ret;
-
-       if (context == NULL || win == NULL)
-               return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
-                               __FUNCTION__, NULL);
-
-       ret = widget_base_context_get_id((widget_base_instance_h)context, &id);
-       if (ret != WIDGET_BASE_ERROR_NONE) {
-               _E("failed to get context id"); /* LCOV_EXCL_LINE */
-               goto fault; /* LCOV_EXCL_LINE */
-       }
-
-       ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC);
-       if (ret_win == NULL) {
-               _E("failed to create window"); /* LCOV_EXCL_LINE */
-               goto fault; /* LCOV_EXCL_LINE */
-       }
-
-       elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
-       elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
-
-       wl_win = ecore_evas_wayland2_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(ret_win)));
-       if (wl_win == NULL) {
-               _E("failed to get wayland window"); /* LCOV_EXCL_LINE */
-               goto fault;
-       }
-
-       ecore_wl2_window_class_set(wl_win, id);
-       elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
-       widget_base_context_window_bind((widget_base_instance_h)context,        id, wl_win);
-
-       /* Set data to use in accessibility */
-       snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid());
-       evas_object_data_set(ret_win, "___PLUGID", strdup(buffer));
-       evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL);
-
-       win_id = ecore_wl2_window_id_get(wl_win);
-       _D("window created: %d", win_id);
-
-       data = (struct instance_data *)widget_base_context_get_user_data(
-                       (widget_base_instance_h)context);
-       if (data == NULL) {
-               data = calloc(1, sizeof(struct instance_data));
-               if (data == NULL) {
-                       _E("failed to alloc instance_data"); /* LCOV_EXCL_LINE */
-                       goto fault; /* LCOV_EXCL_LINE */
-               }
-
-               ret = widget_base_context_set_user_data((widget_base_instance_h)context, data);
-               if (ret != WIDGET_BASE_ERROR_NONE) {
-                       _E("fail to set extra data"); /* LCOV_EXCL_LINE */
-                       goto fault; /* LCOV_EXCL_LINE */
-               }
-       }
-
-       data->win = ret_win;
-       *win = ret_win;
-
-       return WIDGET_ERROR_NONE;
-
-fault:
-       if (ret_win)    /* LCOV_EXCL_LINE */
-               evas_object_del(ret_win); /* LCOV_EXCL_LINE */
-
-       return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */
-}
-
-EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class,
-               const char *class_id,
-               widget_instance_lifecycle_callback_s callback, void *user_data)
-{
-       widget_base_class cls;
-       struct app_class_cb_info *callback_data;
-       widget_class_h wc;
-
-       cls = widget_base_class_get_default();
-
-       /* override methods */
-       cls.ops.create = __class_create;
-       cls.ops.destroy = __class_destroy;
-       cls.ops.pause = __class_pause;
-       cls.ops.resume = __class_resume;
-       cls.ops.resize = __class_resize;
-       cls.ops.update = __class_update;
-
-       callback_data = calloc(1, sizeof(struct app_class_cb_info));
-       if (!callback_data) {
-               _E("failed to calloc : %s", __FUNCTION__);
-               set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
-               return NULL;
-       }
-       callback_data->callback = callback;
-       callback_data->user_data = user_data;
-
-       wc = (widget_class_h)widget_base_class_add(cls, class_id,
-                       callback_data);
-
-       if (!wc) {
-               free(callback_data);
-               return NULL;
-       }
-
-       __class_data_list = g_list_append(__class_data_list, callback_data);
-       set_last_result(WIDGET_ERROR_NONE);
-
-       return wc;
-}
-
-EXPORT_API widget_class_h widget_app_class_create(
-               widget_instance_lifecycle_callback_s callback, void *user_data)
-{
-       char *appid;
-       widget_class_h wc;
-
-       app_get_id(&appid);
-       if (!appid) {
-               LOGE("appid is NULL");
-               return NULL;
-       }
-
-       wc = (widget_class_h)widget_app_class_add(NULL, appid, callback,
-                       user_data);
-       free(appid);
-
-       return wc;
-}
-
-EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag)
-{
-       int ret = 0;
-
-       ret = widget_base_context_set_tag((widget_base_instance_h)context, tag);
-       if (ret != WIDGET_BASE_ERROR_NONE)
-               return widget_app_error(ret, __FUNCTION__, NULL);
-
-       return WIDGET_ERROR_NONE;
-}
-
-EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag)
-{
-       int ret = 0;
-
-       ret = widget_base_context_get_tag((widget_base_instance_h)context, tag);
-       if (ret != WIDGET_BASE_ERROR_NONE)
-               return widget_app_error(ret, __FUNCTION__, NULL);
-
-       return WIDGET_ERROR_NONE;
-}
-
-EXPORT_API int widget_app_context_set_content_info(widget_context_h context,
-               bundle *content_info)
-{
-       int ret = 0;
-
-       ret = widget_base_context_set_content_info(
-                       (widget_base_instance_h)context, content_info);
-       if (ret != WIDGET_BASE_ERROR_NONE)
-               return widget_app_error(ret, __FUNCTION__, NULL);
-
-       return WIDGET_ERROR_NONE;
-}
-
-EXPORT_API int widget_app_context_set_title(widget_context_h context,
-               const char *title)
-{
-       struct instance_data *data = NULL;
-       int ret;
-
-       if (!context || !title) {
-               _E("Invalid parameter %p %p", context, title);
-               return WIDGET_ERROR_INVALID_PARAMETER;
-       }
-
-       data = (struct instance_data *)widget_base_context_get_user_data(
-                       (widget_base_instance_h)context);
-       if (data == NULL) {
-               data = calloc(1, sizeof(struct instance_data));
-               if (data == NULL) {
-                       return widget_app_error(WIDGET_ERROR_FAULT,
-                                       __FUNCTION__, NULL);
-               }
-               ret = widget_base_context_set_user_data(context, data);
-               if (ret != WIDGET_BASE_ERROR_NONE)
-                       widget_app_error(ret, __FUNCTION__, NULL);
-       }
-
-       if (data->win)
-               elm_win_title_set(data->win, title);
-
-       return WIDGET_ERROR_NONE;
-}
diff --git a/src/efl_base/widget_app.cc b/src/efl_base/widget_app.cc
new file mode 100644 (file)
index 0000000..17cd02f
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+* Copyright (c) 2015 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <Elementary.h>
+#include <app_event_internal.hh>
+#include <aul.h>
+#include <aul_app_com.h>
+#include <aul_widget.h>
+#include <dlog.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <system_info.h>
+#include <widget_errno.h>
+#include <widget_instance.h>
+
+#include "common/export_private.hh"
+#include "common/log_private.hh"
+#include "include/widget_app.h"
+#include "include/widget_app_internal.h"
+#include "include/widget_base.hh"
+
+using namespace tizen_cpp;
+namespace {
+
+constexpr const int kIconifyTimeout = 500;
+constexpr const char kFeatureShellAppWidget[] =
+    "http://tizen.org/feature/shell.appwidget";
+constexpr int APP_EVENT_MAX = 7;
+constexpr IAppCore::IEvent::Type __app_event_converter[APP_EVENT_MAX] = {
+  [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY,
+  [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY,
+  [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE,
+  [APP_EVENT_DEVICE_ORIENTATION_CHANGED]
+      = IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED,
+  [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE,
+  [APP_EVENT_SUSPENDED_STATE_CHANGED]
+      = IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE,
+};
+
+class AppWidget : public WidgetBase {
+ public:
+  AppWidget(widget_app_lifecycle_callback_s* callback, void* user_data)
+      : callback_(callback), user_data_(user_data) {}
+
+  int OnCreate() override {
+    WidgetBase::OnCreate();
+    if (callback_ && callback_->create) {
+      if (callback_->create(user_data_) == nullptr) {
+        _E("Failed to create widget");
+        return -1;
+      }
+
+      _D("Widget app is created");
+      aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
+      return 0;
+    }
+
+    return -1;
+  }
+
+  int OnTerminate() override {
+    if (callback_ && callback_->terminate) {
+      callback_->terminate(user_data_);
+      WidgetBase::OnTerminate();
+      _D("Widget app is terminated");
+      aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
+      return 0;
+    }
+
+    WidgetBase::OnTerminate();
+    return -1;
+  }
+
+  void OnLoopInit(int argc, char** argv) override {
+    elm_init(argc, argv);
+  }
+
+  void OnLoopFinish() override {
+    elm_shutdown();
+  }
+
+  void OnLoopRun() override {
+    elm_run();
+  }
+
+  void OnLoopExit() override {
+    elm_exit();
+  }
+
+  int OnTrimMemory() override {
+    _D("Trim memory");
+    elm_cache_all_flush();
+    return WidgetBase::OnTrimMemory();
+  }
+
+ private:
+  widget_app_lifecycle_callback_s* callback_;
+  void* user_data_;
+};
+
+class AppWidgetContext : public WidgetContext {
+ public:
+  class Factory : public AppCoreMultiWindowBase::Context::IFactory {
+   public:
+    Factory(std::string widget_id,
+        widget_instance_lifecycle_callback_s callback, void* user_data)
+        : widget_id_(std::move(widget_id)),
+          callback_(callback),
+          user_data_(user_data) {
+    }
+
+    std::unique_ptr<Context> Create(std::string inst_id,
+        AppCoreMultiWindowBase* app) override {
+      return std::unique_ptr<Context>(
+          new AppWidgetContext(widget_id_, std::move(inst_id), app,
+              callback_, user_data_));
+    }
+
+   private:
+    std::string widget_id_;
+    widget_instance_lifecycle_callback_s callback_;
+    void* user_data_;
+  };
+
+  AppWidgetContext(std::string context_id, std::string inst_id,
+      AppCoreMultiWindowBase* app,
+      widget_instance_lifecycle_callback_s callback, void* user_data)
+      : WidgetContext(std::move(context_id), std::move(inst_id), app),
+          callback_(callback), user_data_(user_data) {}
+
+  bool OnCreate(const tizen_base::Bundle& contents, int w, int h) override {
+    int ret = -1;
+    if (callback_.create) {
+      ret = callback_.create(reinterpret_cast<widget_context_h>(this),
+          contents.GetHandle(), w, h, user_data_);
+      aul_widget_write_log(LOG_TAG, "[%s:%d]  ret : %d",
+          __FUNCTION__, __LINE__, ret);
+    }
+
+    return ret == 0;
+  }
+
+  void OnDestroy(DestroyType reason,
+      const tizen_base::Bundle& contents) override {
+    if (callback_.destroy) {
+      callback_.destroy(reinterpret_cast<widget_context_h>(this),
+          reason == DestroyType::PERMANENT ? WIDGET_APP_DESTROY_TYPE_PERMANENT :
+          WIDGET_APP_DESTROY_TYPE_TEMPORARY, contents.GetHandle(), user_data_);
+      aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
+    }
+
+    UnsetIconifyTimer();
+  }
+
+  void OnPause() override {
+    UnsetIconifyTimer();
+    SetIconifyTimer();
+
+    WidgetContext::OnPause();
+    if (callback_.pause) {
+      callback_.pause(reinterpret_cast<widget_context_h>(this), user_data_);
+    }
+  }
+
+  void OnResume() override {
+    UnsetIconifyTimer();
+
+    if (is_iconified_) {
+      Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get(
+          ecore_evas_ecore_evas_get(evas_object_evas_get(win_)));
+      if (win) {
+        ecore_wl2_window_iconified_set(win, EINA_FALSE);
+        is_iconified_ = false;
+        _D("Set iconify false");
+      }
+    }
+
+    WidgetContext::OnResume();
+    if (callback_.resume) {
+      callback_.resume(reinterpret_cast<widget_context_h>(this), user_data_);
+    }
+  }
+
+  void OnResize(int w, int h) override {
+    WidgetContext::OnResize(w, h);
+
+    if (win_)
+      evas_object_resize(win_, w, h);
+    else
+      _E("Failed to find window");
+
+    if (callback_.resize) {
+      callback_.resize(reinterpret_cast<widget_context_h>(this),
+          w, h, user_data_);
+    }
+  }
+
+  void OnUpdate(const tizen_base::Bundle& contents, bool force) override {
+    WidgetContext::OnUpdate(contents, force);
+    if (callback_.update) {
+      callback_.update(reinterpret_cast<widget_context_h>(this),
+          contents.GetHandle(), force, user_data_);
+    }
+  }
+
+  void SetTag(void* tag) {
+    tag_ = tag;
+  }
+
+  void* GetTag() const {
+    return tag_;
+  }
+
+  Evas_Object* GetWindow() const {
+    return win_;
+  }
+
+  void SetWindow(Evas_Object* win) {
+    win_ = win;
+  }
+
+ private:
+  void SetIconifyTimer() {
+    if (iconify_timer_)
+      return;
+
+    iconify_timer_ = g_timeout_add(kIconifyTimeout,
+        [](gpointer user_data) -> gboolean{
+          AppWidgetContext* cxt = static_cast<AppWidgetContext*>(user_data);
+          Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get(
+              ecore_evas_ecore_evas_get(evas_object_evas_get(cxt->win_)));
+          if (win) {
+            ecore_wl2_window_iconified_set(win, EINA_TRUE);
+            cxt->is_iconified_ = true;
+            _D("Set iconify true");
+          }
+
+          cxt->iconify_timer_ = 0;
+          return G_SOURCE_REMOVE;
+        }, this);
+  }
+
+  void UnsetIconifyTimer() {
+    if (iconify_timer_) {
+      g_source_remove(iconify_timer_);
+      iconify_timer_ = 0;
+    }
+  }
+
+ private:
+  widget_instance_lifecycle_callback_s callback_;
+  void* user_data_;
+  Evas_Object* win_ = nullptr;
+  guint iconify_timer_ = 0;
+  bool is_iconified_ = false;
+  void* tag_ = nullptr;
+};
+
+std::unique_ptr<AppWidget> __app_widget;
+std::list<std::shared_ptr<AppEvent>> __pending_app_events;
+
+}  // namespace
+
+API int widget_app_main(int argc, char** argv,
+    widget_app_lifecycle_callback_s* callback, void* user_data) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (argc <= 0 || argv == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  if (callback->create == nullptr) {
+    _E("widget_app_create_cb() callback must be registered");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  try {
+    __app_widget = std::make_unique<AppWidget>(callback, user_data);
+    for (auto& i : __pending_app_events)
+      __app_widget->AddEvent(i);
+
+    __app_widget->Run(argc, argv);
+  } catch (std::runtime_error& e) {
+    return WIDGET_ERROR_FAULT;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_exit(void) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (__app_widget.get() == nullptr)
+    return WIDGET_ERROR_FAULT;
+
+  __app_widget->Exit();
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_terminate_context(widget_context_h context) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  cxt->ExitAsync();
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_foreach_context(widget_context_cb cb, void* data) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (cb == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  if (__app_widget.get() == nullptr)
+    return WIDGET_ERROR_FAULT;
+
+  auto l = __app_widget->GetContexts();
+  for (auto& i : l) {
+    if (!cb(reinterpret_cast<widget_context_h>(i.get()), data))
+      break;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_add_event_handler(app_event_handler_h* event_handler,
+    app_event_type_e event_type, app_event_cb callback, void* user_data) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (event_handler == nullptr || callback == nullptr)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  if (event_type < APP_EVENT_LOW_MEMORY ||
+      event_type > APP_EVENT_REGION_FORMAT_CHANGED)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  auto* app_event = new (std::nothrow) AppEvent(
+      ::__app_event_converter[event_type], callback, user_data);
+  if (app_event == nullptr) {
+    _E("Out of memory");
+    return WIDGET_ERROR_OUT_OF_MEMORY;
+  }
+
+  auto* h = new (std::nothrow) std::shared_ptr<AppEvent>(app_event);
+  if (h == nullptr) {
+    _E("Out of memory");
+    delete app_event;
+    return WIDGET_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (__app_widget.get() != nullptr)
+    __app_widget->AddEvent(*h);
+  else
+    __pending_app_events.push_back(*h);
+
+  *event_handler = reinterpret_cast<app_event_handler_h>(h);
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_remove_event_handler(app_event_handler_h event_handler) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (event_handler == nullptr)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  auto* h = reinterpret_cast<std::shared_ptr<AppEvent>*>(event_handler);
+
+  if (__app_widget.get() != nullptr) {
+    if (!__app_widget->RemoveEvent(*h))
+      return WIDGET_ERROR_INVALID_PARAMETER;
+  } else {
+    __pending_app_events.remove(*h);
+  }
+
+  delete h;
+  return WIDGET_ERROR_NONE;
+}
+
+API const char* widget_app_get_id(widget_context_h context) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0) {
+    set_last_result(WIDGET_ERROR_FAULT);
+    return nullptr;
+  }
+
+  if (!feature) {
+    set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
+    return nullptr;
+  }
+
+  if (context == nullptr) {
+    set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+    return nullptr;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  const std::string& id = cxt->GetInstId();
+  set_last_result(WIDGET_ERROR_NONE);
+  return id.c_str();
+}
+
+API int widget_app_get_elm_win(widget_context_h context, Evas_Object** win) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr || win == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  const std::string& id = cxt->GetInstId();
+
+  Evas_Object* ret_win = elm_win_add(nullptr, id.c_str(), ELM_WIN_BASIC);
+  if (ret_win == nullptr) {
+    _E("Failed to create window");
+    return WIDGET_ERROR_FAULT;
+  }
+
+  elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
+  int rots[3] = { 0, };
+  elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
+
+  Ecore_Wl2_Window* wl_win = ecore_evas_wayland2_window_get(
+      ecore_evas_ecore_evas_get(evas_object_evas_get(ret_win)));
+  if (wl_win == nullptr) {
+    _E("Failed to get wayland window");
+    evas_object_del(ret_win);
+    return WIDGET_ERROR_FAULT;
+  }
+
+  ecore_wl2_window_class_set(wl_win, id.c_str());
+  elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
+  cxt->WindowBind(id, wl_win);
+
+  /* Set data to use in accessibility */
+  std::string plug_id = id + ":" + std::to_string(getpid());
+  evas_object_data_set(ret_win, "___PLUGID", strdup(plug_id.c_str()));
+  evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL,
+      [](void *data, Evas *e, Evas_Object *obj, void *event_info) {
+        char* plug_id = static_cast<char*>(
+            evas_object_data_del(obj, "___PLUGID"));
+        free(plug_id);
+      }, nullptr);
+
+  int win_id = ecore_wl2_window_id_get(wl_win);
+  _D("Window created: %d", win_id);
+
+  cxt->SetWindow(ret_win);
+  *win = ret_win;
+  return WIDGET_ERROR_NONE;
+}
+
+API widget_class_h widget_app_class_add(widget_class_h widget_class,
+    const char* class_id, widget_instance_lifecycle_callback_s callback,
+    void* user_data) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0) {
+    set_last_result(WIDGET_ERROR_FAULT);
+    return nullptr;
+  }
+
+  if (!feature) {
+    set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
+    return nullptr;
+  }
+
+  if (class_id == nullptr || callback.create == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+    return nullptr;
+  }
+
+  if (__app_widget.get() == nullptr) {
+    set_last_result(WIDGET_ERROR_FAULT);
+    return nullptr;
+  }
+
+  auto factory = std::shared_ptr<AppCoreMultiWindowBase::Context::IFactory>(
+      new (std::nothrow) AppWidgetContext::Factory(
+          class_id, callback, user_data));
+  if (factory.get() == nullptr) {
+    set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
+    return nullptr;
+  }
+
+  __app_widget->AddContextFactory(std::move(factory), class_id);
+  set_last_result(WIDGET_ERROR_NONE);
+  int dummy;
+  widget_class_h cls = reinterpret_cast<widget_class_h>(&dummy);
+  return cls;
+}
+
+API widget_class_h widget_app_class_create(
+    widget_instance_lifecycle_callback_s callback, void* user_data) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0) {
+    set_last_result(WIDGET_ERROR_FAULT);
+    return nullptr;
+  }
+
+  if (!feature) {
+    set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
+    return nullptr;
+  }
+
+  if (callback.create == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+    return nullptr;
+  }
+
+  char* appid = nullptr;
+  app_get_id(&appid);
+  if (appid == nullptr) {
+    LOGE("app_get_id() is failed");
+    return nullptr;
+  }
+  std::unique_ptr<char, decltype(std::free)*> ptr(appid, std::free);
+
+  return static_cast<widget_class_h>(
+      widget_app_class_add(nullptr, appid, callback, user_data));
+}
+
+API int widget_app_context_set_tag(widget_context_h context, void* tag) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  cxt->SetTag(tag);
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_context_get_tag(widget_context_h context, void** tag) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr || tag == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  *tag = cxt->GetTag();
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_context_set_content_info(widget_context_h context,
+    bundle* content_info) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr || content_info == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  ret = cxt->SetContents(tizen_base::Bundle(content_info));
+  if (ret != WIDGET_ERROR_NONE) {
+    _E("Failed to set content");
+    return static_cast<widget_error_e>(ret);
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_context_set_title(widget_context_h context,
+    const char* title) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (context == nullptr || title == nullptr) {
+    _E("Invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
+  if (cxt->GetWindow())
+    elm_win_title_set(cxt->GetWindow(), title);
+
+  return WIDGET_ERROR_NONE;
+}
+
+API int widget_app_restart(void) {
+  bool feature;
+  int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
+  if (ret < 0)
+    return WIDGET_ERROR_FAULT;
+
+  if (!feature)
+    return WIDGET_ERROR_NOT_SUPPORTED;
+
+  if (__app_widget.get() == nullptr)
+    return WIDGET_ERROR_IO_ERROR;
+
+  std::string class_id;
+  auto l = __app_widget->GetContexts();
+  for (auto& i : l) {
+    class_id = i->GetContextId();
+    break;
+  }
+
+  if (class_id.empty())
+    return WIDGET_ERROR_IO_ERROR;
+
+  tizen_base::Bundle b;
+  int status = AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST;
+  std::vector<unsigned char> v;
+  auto* p = reinterpret_cast<const uint8_t*>(&status);
+  std::copy(p, p + sizeof(int), std::back_inserter(v));
+
+  b.Add(AUL_K_WIDGET_ID, class_id);
+  b.Add(AUL_K_WIDGET_STATUS, v);
+
+  std::string endpoint = __app_widget->GetViewerEndpoint();
+  ret = aul_app_com_send(endpoint.empty() ? nullptr : endpoint.c_str(),
+      b.GetHandle());
+  if (ret != AUL_R_OK) {
+    _E("Failed to send restart request");
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
diff --git a/src/efl_base/widget_app_internal.c b/src/efl_base/widget_app_internal.c
deleted file mode 100644 (file)
index cbd7e4c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <bundle.h>
-#include <bundle_internal.h>
-#include <aul.h>
-#include <aul_app_com.h>
-#include <dlog.h>
-#include <appcore_multiwindow_base.h>
-
-#include "widget_app.h"
-#include "widget-log.h"
-#include "widget-private.h"
-#include "widget_app_internal.h"
-#include "widget-private.h"
-#include "widget_base.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_WIDGET_APPLICATION"
-static char *__class_id;
-
-/* LCOV_EXCL_START */
-static void __inst_cb(const char *class_id, const char *id,
-               appcore_multiwindow_base_instance_h cxt, void *data)
-{
-       if (!__class_id)
-               __class_id = strdup(class_id);
-}
-/* LCOV_EXCL_STOP */
-
-EXPORT_API int widget_app_restart(void)
-{
-       int ret;
-       int status = AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST;
-       bundle *kb;
-
-       appcore_multiwindow_base_instance_foreach_full(__inst_cb, NULL);
-
-       kb = bundle_create();
-       bundle_add_str(kb, AUL_K_WIDGET_ID, __class_id);
-       bundle_add_byte(kb, AUL_K_WIDGET_STATUS, &status, sizeof(int));
-       ret = aul_app_com_send(widget_base_get_viewer_endpoint(), kb);
-       bundle_free(kb);
-       if (__class_id) {
-               free(__class_id);
-               __class_id = NULL;
-       }
-
-       if (ret != AUL_R_OK) {
-               _E("failed to kill app");
-               return WIDGET_ERROR_IO_ERROR;
-       }
-       return WIDGET_ERROR_NONE;
-}
-
diff --git a/src/efl_base/widget_error.c b/src/efl_base/widget_error.c
deleted file mode 100644 (file)
index cd79e5f..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <string.h>
-#include <libintl.h>
-
-#include <dlog.h>
-#include <widget_errno.h>
-
-#include "widget-private.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_WIDGET_APPLICATION"
-
-static const char *widget_app_error_to_string(widget_error_e error)
-{
-       switch (error) {
-       case WIDGET_ERROR_NONE:
-               return "NONE";
-       case WIDGET_ERROR_INVALID_PARAMETER:
-               return "INVALID_PARAMETER";
-       case WIDGET_ERROR_OUT_OF_MEMORY:
-               return "OUT_OF_MEMORY"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_RESOURCE_BUSY:
-               return "RESOURCE_BUSY"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_PERMISSION_DENIED:
-               return "PERMISSION_DENIED"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_CANCELED:
-               return "CANCELED"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_IO_ERROR:
-               return "IO_ERROR"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_TIMED_OUT:
-               return "TIMED_OUT"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_NOT_SUPPORTED:
-               return "NOT_SUPPORTED"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_FILE_NO_SPACE_ON_DEVICE:
-               return "FILE_NO_SPACE_ON_DEVICE"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_FAULT:
-               return "FAULT"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_ALREADY_EXIST:
-               return "ALREADY_EXIST"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_ALREADY_STARTED:
-               return "ALREADY_STARTED"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_NOT_EXIST:
-               return "NOT_EXIST"; /* LCOV_EXCL_LINE */
-       case WIDGET_ERROR_DISABLED:
-               return "DISABLED"; /* LCOV_EXCL_LINE */
-       default:
-               return "UNKNOWN"; /* LCOV_EXCL_LINE */
-       }
-}
-
-int widget_app_error(widget_error_e error, const char *function,
-               const char *description)
-{
-       if (description) {
-               LOGE("[%s] %s(0x%08x) : %s", function,
-                               widget_app_error_to_string(error), error,
-                               description);
-       } else {
-               LOGE("[%s] %s(0x%08x)", function,
-                               widget_app_error_to_string(error), error);
-       }
-
-       return error;
-}
-
index 64fd8a49b733a1d07fd8311ad5438dead2f88e95..7a2beb75527acca994c784de4c45b79293f8e89f 100644 (file)
@@ -1,25 +1,40 @@
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ UNIT_TESTS_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock/ UNIT_TESTS_SRCS)
-ADD_EXECUTABLE(${TARGET_WIDGET_APPLICATION_UNIT_TEST}
-  ${UNIT_TESTS_SRCS}
-)
+
+ADD_EXECUTABLE(${TARGET_WIDGET_APPLICATION_UNIT_TEST} ${UNIT_TESTS_SRCS})
 
 TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC
-  "${CMAKE_CURRENT_SOURCE_DIR}/../"
-  "${CMAKE_CURRENT_SOURCE_DIR}/../../include"
-  "${CMAKE_CURRENT_SOURCE_DIR}/../../src/efl_base"
+  ${CMAKE_CURRENT_SOURCE_DIR}/../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../src/
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../src/base
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../src/efl_base
 )
 
 APPLY_PKG_CONFIG(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC
+  APPCORE_COMMON_DEPS
+  APPCORE_MULTIWINDOW_DEPS
+  APPCORE_MULTIWINDOW_OLD_DEPS
+  AUL_DEP
+  BUNDLE_DEPS
+  CAPI_APP_COMMON_DEP
+  DLOG_DEPS
+  ECORE_WL2_DEPS
+  ELEMENTARY_DEP
   GLIB_DEPS
   GMOCK_DEPS
-  BUNDLE_DEPS
-  GOBJECT_DEPS
+  SCREEN_CONNECTOR_PROVIDER_DEPS
+  SYSTEM_INFO_DEPS
+  WIDGET_SERVICE_DEPS
 )
 
-TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC ${TARGET_WIDGET_BASE} ${TARGET_WIDGET_APPLICATION})
-SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PROPERTIES COMPILE_FLAGS "-fPIE")
-SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PROPERTIES LINK_FLAGS "-pie")
+TARGET_LINK_LIBRARIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST} PUBLIC
+  ${TARGET_WIDGET_APPLICATION})
+SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST}
+  PROPERTIES COMPILE_FLAGS "-fPIE")
+SET_TARGET_PROPERTIES(${TARGET_WIDGET_APPLICATION_UNIT_TEST}
+  PROPERTIES LINK_FLAGS "-pie")
 
 ADD_TEST(
   NAME ${TARGET_WIDGET_APPLICATION_UNIT_TEST}
index 5fa214e94f93c61d3f7fe6e6a33f2662219aed48..7219d8937bb984115733359932661fbfd6c3deca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
 #define UNIT_TESTS_MOCK_APP_COMMON_MOCK_H_
 
 #include <gmock/gmock.h>
-#include <appcore_multiwindow_base.h>
 
 #include "mock/module_mock.h"
 
index fe09a24ebef52bc1697d0742e8afa655a1e0e54a..c66bd8e111b99880aa4afcdf02ae8a459ca407ef 100644 (file)
 #include "unit_tests/mock/mock_hook.h"
 #include "unit_tests/mock/test_fixture.h"
 
-extern "C" int appcore_multiwindow_base_init(
-        appcore_multiwindow_base_ops ops, int argc, char **argv, void *data) {
-  return MOCK_HOOK_P4(MultiWindowBaseMock, appcore_multiwindow_base_init,
-        ops, argc, argv, data);
-}
-
-extern "C" const char *appcore_multiwindow_base_instance_get_id(
-        appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_get_id, context);
-}
-
-extern "C" void *appcore_multiwindow_base_instance_get_extra(
-        appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_get_extra, context);
-}
-
-extern "C" const char* appcore_multiwindow_base_instance_get_class_id(
-        appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_get_class_id, context);
-}
 
-extern "C" void appcore_multiwindow_base_class_add(
-        appcore_multiwindow_base_class cls) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_class_add, cls);
-}
+namespace tizen_cpp {
 
-extern "C" void appcore_multiwindow_base_instance_drop(
-      appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_drop, context);
+void AppCoreMultiWindowBase::Run(int argc, char** argv) {
+  TestFixture::GetMock<MultiWindowBaseMock>().real_ = this;
+  TestFixture::GetMock<MultiWindowBaseMock>().Run(argc, argv);
+  TestFixture::GetMock<MultiWindowBaseMock>().real_ = nullptr;
 }
 
-extern "C" appcore_multiwindow_base_instance_h
-      appcore_multiwindow_base_instance_find(const char *id) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_find, id);
+int AppCoreMultiWindowBase::OnCreate() {
+  return TestFixture::GetMock<MultiWindowBaseMock>().OnCreate();
 }
 
-extern "C" const appcore_multiwindow_base_class *
-      appcore_multiwindow_base_instance_get_class(
-            appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_get_class, context);
-}
-
-extern "C" void appcore_multiwindow_base_instance_exit(
-      appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_exit, context);
-}
-
-extern "C" void appcore_multiwindow_base_instance_pause(
-      appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_pause, context);
-}
-
-extern "C" void appcore_multiwindow_base_instance_resume(
-      appcore_multiwindow_base_instance_h context) {
-  return MOCK_HOOK_P1(MultiWindowBaseMock,
-        appcore_multiwindow_base_instance_resume, context);
-}
+}  // namespace tizen_cpp
index 06ec917a914b482f9231fe66cb2d910390213c86..0f044f842d1b324abca6acf8ec4b7ea424a664b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
 #define UNIT_TESTS_MOCK_APPCORE_MULTIWINDOW_BASE_MOCK_H_
 
 #include <gmock/gmock.h>
-#include <appcore_multiwindow_base.h>
+#include <app_core_multi_window_base.hh>
 
 #include "mock/module_mock.h"
 
@@ -26,28 +26,10 @@ class MultiWindowBaseMock : public virtual ModuleMock {
  public:
   virtual ~MultiWindowBaseMock() {}
 
-  MOCK_METHOD4(appcore_multiwindow_base_init,
-      int(appcore_multiwindow_base_ops, int, char **, void *));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_get_id,
-      const char *(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_get_extra,
-      void *(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_get_class_id,
-      const char *(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_class_add,
-      void(appcore_multiwindow_base_class));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_drop,
-      void(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_find,
-      appcore_multiwindow_base_instance_h(const char *));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_get_class,
-      const appcore_multiwindow_base_class *(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_exit,
-      void(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_pause,
-      void(appcore_multiwindow_base_instance_h));
-  MOCK_METHOD1(appcore_multiwindow_base_instance_resume,
-      void(appcore_multiwindow_base_instance_h));
+  MOCK_METHOD2(Run, void(int, char**));
+  MOCK_METHOD0(OnCreate, int());
+
+  tizen_cpp::AppCoreMultiWindowBase* real_ = nullptr;
 };
 
 #endif  // UNIT_TESTS_MOCK_APPCORE_MULTIWINDOW_BASE_MOCK_H_
index 76ed24750444a47f176d56086509138d5bf8a917..65f947c21ca9cd6becfdd4ae7ca15100e6cf3b48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "unit_tests/mock/mock_hook.h"
 #include "unit_tests/mock/test_fixture.h"
 
-extern "C" int aul_app_get_pkgid_bypid(int pid, char *pkgid, int len) {
+extern "C" int aul_app_get_appid_bypid(int pid, char* appid, int len) {
+  return MOCK_HOOK_P3(AulMock, aul_app_get_appid_bypid, pid, appid, len);
+}
+
+extern "C" int aul_app_get_pkgid_bypid(int pid, char* pkgid, int len) {
   return MOCK_HOOK_P3(AulMock, aul_app_get_pkgid_bypid, pid, pkgid, len);
 }
+
+extern "C" int aul_widget_send_status_to_service(const char* class_id,
+    const char *instance_id, const char *sender_pkgid, int status) {
+  return MOCK_HOOK_P4(AulMock, aul_widget_send_status_to_service,
+      class_id, instance_id, sender_pkgid, status);
+}
+
+extern "C" int aul_widget_send_status_to_viewer(const char* class_id,
+    const char *instance_id, const char *viewer_endpoint,
+    int status, int err, bundle *extra) {
+  return MOCK_HOOK_P6(AulMock, aul_widget_send_status_to_viewer,
+      class_id, instance_id, viewer_endpoint, status, err, extra);
+}
+
+extern "C" int aul_notify_exit(void) {
+  return MOCK_HOOK_P0(AulMock, aul_notify_exit);
+}
+
+extern "C" int aul_widget_write_log(const char* tag, const char* format, ...) {
+  return 0;
+}
+
+extern "C" int aul_widget_instance_del(const char* widget_id,
+    const char* instance_id) {
+  return 0;
+}
+
+extern "C" int aul_status_update(int status) {
+  return 0;
+}
index 359db71bcb9023fe7cdace810afb9e67aa51543f..ef0f1e4294746447b3c6184d87254e8c6d4a63a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
 #define UNIT_TESTS_MOCK_AUL_MOCK_H_
 
 #include <gmock/gmock.h>
-#include <appcore_multiwindow_base.h>
+#include <bundle.h>
 
 #include "mock/module_mock.h"
 
@@ -26,7 +26,13 @@ class AulMock : public virtual ModuleMock {
  public:
   virtual ~AulMock() {}
 
+  MOCK_METHOD3(aul_app_get_appid_bypid, int (int , char *, int));
   MOCK_METHOD3(aul_app_get_pkgid_bypid, int (int , char *, int));
+  MOCK_METHOD4(aul_widget_send_status_to_service, int (const char*,
+      const char*, const char*, int));
+  MOCK_METHOD6(aul_widget_send_status_to_viewer, int (const char*,
+      const char*, const char*, int, int, bundle*));
+  MOCK_METHOD0(aul_notify_exit, int ());
 };
 
 #endif  // UNIT_TESTS_MOCK_AUL_MOCK_H_
index 05bf3696f0cfb00949bf0f315b2e36c75ea5fb46..632e75417bdceebe36a9c60970aeceb20f1c993a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "unit_tests/mock/test_fixture.h"
 
 
-extern "C" Evas_Object * elm_win_add(Evas_Object *parent,
-        const char *name, Elm_Win_Type type) {
+extern "C" Evas_Object* elm_win_add(Evas_Object* parent,
+        const charname, Elm_Win_Type type) {
   return MOCK_HOOK_P3(ElmMock, elm_win_add, parent, name, type);
 }
 
 extern "C" void elm_win_wm_rotation_preferred_rotation_set(
-        Evas_Object *obj, int rotation) {
+        Evas_Objectobj, int rotation) {
   return MOCK_HOOK_P2(
           ElmMock, elm_win_wm_rotation_preferred_rotation_set, obj, rotation);
 }
 
-extern "C" void elm_win_wm_rotation_available_rotations_set(Elm_Win *obj,
-        const int *rotations, unsigned int count) {
+extern "C" void elm_win_wm_rotation_available_rotations_set(Elm_Winobj,
+        const introtations, unsigned int count) {
   return MOCK_HOOK_P3(
           ElmMock, elm_win_wm_rotation_available_rotations_set,
           obj, rotations, count);
 }
 
-extern "C" int elm_win_aux_hint_add(Evas_Object *obj,
-        const char *hint, const char *val) {
+extern "C" int elm_win_aux_hint_add(Evas_Objectobj,
+        const char* hint, const char* val) {
   return MOCK_HOOK_P3(ElmMock, elm_win_aux_hint_add, obj, hint, val);
 }
+
+extern "C" void elm_exit(void) {
+}
diff --git a/test/unit_tests/mock/widget_service_mock.cc b/test/unit_tests/mock/widget_service_mock.cc
new file mode 100644 (file)
index 0000000..36803b4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "unit_tests/mock/widget_service_mock.h"
+
+#include <gio/gio.h>
+
+#include "unit_tests/mock/mock_hook.h"
+#include "unit_tests/mock/test_fixture.h"
+
+extern "C" int widget_instance_convert_event_to_lifecycle_status(int event) {
+  return MOCK_HOOK_P1(WidgetServiceMock,
+      widget_instance_convert_event_to_lifecycle_status, event);
+}
diff --git a/test/unit_tests/mock/widget_service_mock.h b/test/unit_tests/mock/widget_service_mock.h
new file mode 100644 (file)
index 0000000..477777f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_
+#define UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "mock/module_mock.h"
+
+class WidgetServiceMock : public virtual ModuleMock {
+ public:
+  virtual ~WidgetServiceMock() {}
+
+  MOCK_METHOD1(widget_instance_convert_event_to_lifecycle_status, int (int));
+};
+
+#endif  // UNIT_TESTS_MOCK_WIDGET_SERVICE_MOCK_H_
+
index 3b3d2dcf45c685ae6ddecc620b8a15b1bbae89de..7c73261d060438d94fa0f19f13a8c92b3c56824e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
 #include <bundle_cpp.h>
 #include <bundle_internal.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
 
 #include <iostream>
 #include <memory>
 
-#include "widget_app.h"
-#include "widget_app_efl.h"
-#include "unit_tests/mock/gio_mock.h"
-#include "unit_tests/mock/ecore_wl2_mock.h"
-#include "unit_tests/mock/system_info_mock.h"
-#include "unit_tests/mock/appcore_multiwindow_base_mock.h"
+#include "include/widget_app.h"
+#include "include/widget_app_efl.h"
 #include "unit_tests/mock/app_common_mock.h"
-#include "unit_tests/mock/elm_mock.h"
+#include "unit_tests/mock/appcore_multiwindow_base_mock.h"
 #include "unit_tests/mock/aul_mock.h"
+#include "unit_tests/mock/ecore_wl2_mock.h"
+#include "unit_tests/mock/elm_mock.h"
+#include "unit_tests/mock/gio_mock.h"
+#include "unit_tests/mock/system_info_mock.h"
 #include "unit_tests/mock/test_fixture.h"
+#include "unit_tests/mock/widget_service_mock.h"
 
 using ::testing::_;
 using ::testing::DoAll;
@@ -40,41 +41,7 @@ using ::testing::Return;
 using ::testing::SetArgPointee;
 using ::testing::Invoke;
 
-typedef struct _widget_base_instance_data {
-  bundle* args;
-  char* id;
-  char* content;
-  void* tag;
-  double period;
-  guint periodic_timer;
-  bool pending_update;
-  char* pending_content;
-  void* user_data;
-} widget_base_instance_data;
-
-struct _widget_context {
-  int context;
-};
-
-class Mocks : public ::testing::NiceMock<GioMock>,
-              public ::testing::NiceMock<MultiWindowBaseMock>,
-              public ::testing::NiceMock<AppCommonMock>,
-              public ::testing::NiceMock<ElmMock>,
-              public ::testing::NiceMock<AulMock>,
-              public ::testing::NiceMock<SystemInfoMock>,
-              public ::testing::NiceMock<EcoreWl2Mock> {};
-
-class WidgetAppTest : public TestFixture {
- public:
-  WidgetAppTest() : TestFixture(std::make_unique<Mocks>()) {}
-  virtual ~WidgetAppTest() {}
-
-  virtual void SetUp() {
-  }
-
-  virtual void TearDown() {
-  }
-};
+namespace {
 
 int __instance_create_cb(widget_context_h context, bundle* content,
     int w, int h, void* user_data) {
@@ -104,10 +71,6 @@ int __instance_update_cb(widget_context_h context,
   return 0;
 }
 
-widget_class_h __app_create_cb(void* user_data) {
-  return nullptr;
-}
-
 void __app_terminate_cb(void* user_data) {
 }
 
@@ -116,187 +79,178 @@ int __app_get_id_fake(char** id) {
   return 0;
 }
 
-int __aul_app_get_pkgid_bypid_fake(int pid, char* pkgid, int len) {
-  snprintf(pkgid, 10, "%s", "test");
+int __aul_app_get_appid_bypid_fake(int pid, char* appid, int len) {
+  snprintf(appid, len, "%s", "test");
   return 0;
 }
 
-struct instance_data {
-  Evas_Object* win;
-  guint iconify_timer;
-  bool is_iconified;
-};
-
-void* __appcore_multiwindow_base_instance_get_extra_fake(
-    appcore_multiwindow_base_instance_h handle) {
-  widget_base_instance_data* data = (widget_base_instance_data*)
-      calloc(1, sizeof(widget_base_instance_data));
-  data->args = bundle_create();
-  bundle_add_str(data->args, "__AUL_WIDGET_ID__", "test");
-  bundle_add_str(data->args, "__WIDGET_OP__", "optest");
-  bundle_add_str(data->args, "__WIDGET_WIDTH__", "320");
-  bundle_add_str(data->args, "__WIDGET_HEIGHT__", "320");
-  data->pending_content = strdup("test");
-  data->content = strdup("test");
-  data->id = strdup("id");
-  data->user_data = calloc(1, sizeof (struct instance_data));
-
-  return data;
-}
-
-const char* __appcore_multiwindow_base_instance_get_id_fake(
-    appcore_multiwindow_base_instance_h handle) {
-  return strdup("test");
+int __aul_app_get_pkgid_bypid_fake(int pid, char* pkgid, int len) {
+  snprintf(pkgid, len, "%s", "test");
+  return 0;
 }
 
-const char* __appcore_multiwindow_base_instance_get_class_id_fake(
-    appcore_multiwindow_base_instance_h context) {
-  return strdup("test");
+void __app_event_cb(app_event_info_h event_info, void *user_data) {
 }
 
-appcore_multiwindow_base_class __cls;
-void __appcore_multiwindow_base_class_add_fake(
-    appcore_multiwindow_base_class cls) {
-  __cls = cls;
-  cls.create(nullptr, nullptr);
-  cls.terminate(nullptr, nullptr);
-  cls.pause((appcore_multiwindow_base_instance_h)
-      calloc(1, sizeof(char)), nullptr);
-  cls.resume((appcore_multiwindow_base_instance_h)
-      calloc(1, sizeof(char)), nullptr);
+bool __widget_context_cb(widget_context_h context, void *user_data) {
+  return true;
 }
 
-int __appcore_multiwindow_base_init_fake(appcore_multiwindow_base_ops ops,
-    int argc, char** argv, void* data) {
-  tizen_base::Bundle b;
-
-  b.Add("__WIDGET_WIDTH__", "320");
-  b.Add("__WIDGET_HEIGHT__", "320");
-  b.Add("__AUL_WIDGET_INSTANCE_ID__", "instance_id");
-  b.Add("__AUL_WIDGET_ID__", "test");
-  b.Add("__WIDGET_OP__", "create");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "resize");
-  ops.base.control(b.GetHandle(), nullptr);
+}  // namespace
 
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "update");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "destroy");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "resume");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "pause");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "terminate");
-  ops.base.control(b.GetHandle(), nullptr);
-
-  b.Delete("__WIDGET_OP__");
-  b.Add("__WIDGET_OP__", "period");
-  ops.base.control(b.GetHandle(), nullptr);
+class Mocks : public ::testing::NiceMock<GioMock>,
+              public ::testing::NiceMock<MultiWindowBaseMock>,
+              public ::testing::NiceMock<AppCommonMock>,
+              public ::testing::NiceMock<WidgetServiceMock>,
+              public ::testing::NiceMock<ElmMock>,
+              public ::testing::NiceMock<AulMock>,
+              public ::testing::NiceMock<SystemInfoMock>,
+              public ::testing::NiceMock<EcoreWl2Mock> {};
 
-  ops.base.create(nullptr);
-  ops.base.terminate(nullptr);
+class WidgetAppTest : public TestFixture {
+ public:
+  WidgetAppTest() : TestFixture(std::make_unique<Mocks>()) {}
+  virtual ~WidgetAppTest() {}
 
-  return 0;
-}
+  virtual void SetUp() {
+  }
 
-TEST_F(WidgetAppTest, widget_app_main) {
-  tizen_base::Bundle b;
-  b.Add("__AUL_WIDGET_VIEWER__", "test");
-  int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE");
-  ASSERT_EQ(ret, BUNDLE_ERROR_NONE);
+  virtual void TearDown() {
+  }
 
-  char** argv = nullptr;
-  int argc = bundle_export_to_argv(b.GetHandle(), &argv);
-  ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
-  ASSERT_NE(argv, nullptr);
-  ASSERT_NE(argc, 0);
+  void PrepareTest(widget_app_create_cb created_cb, void* data) {
+    tizen_base::Bundle b;
+    b.Add("__AUL_WIDGET_VIEWER__", "test");
+    int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE");
+    ASSERT_EQ(ret, BUNDLE_ERROR_NONE);
+
+    char** argv = nullptr;
+    int argc = bundle_export_to_argv(b.GetHandle(), &argv);
+    ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
+    ASSERT_NE(argv, nullptr);
+    ASSERT_NE(argc, 0);
+
+    widget_app_lifecycle_callback_s callback;
+    callback.create = created_cb;
+    callback.terminate = __app_terminate_cb;
+
+    EXPECT_CALL(GetMock<SystemInfoMock>(),
+        system_info_get_platform_bool(_, _)).
+            WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(0)));
+
+    EXPECT_CALL(GetMock<AulMock>(),
+        aul_app_get_appid_bypid(_, _, _)).
+            WillOnce(Invoke(__aul_app_get_appid_bypid_fake));
+    EXPECT_CALL(GetMock<AulMock>(),
+        aul_app_get_pkgid_bypid(_, _, _)).
+            WillOnce(Invoke(__aul_app_get_pkgid_bypid_fake));
+    EXPECT_CALL(GetMock<AulMock>(),
+        aul_widget_send_status_to_service(_, _, _, _)).
+            WillRepeatedly(Return(0));
+    EXPECT_CALL(GetMock<AulMock>(),
+        aul_widget_send_status_to_viewer(_, _, _, _, _, _)).
+            WillRepeatedly(Return(0));
+    EXPECT_CALL(GetMock<WidgetServiceMock>(),
+        widget_instance_convert_event_to_lifecycle_status(_)).
+            WillRepeatedly(Return(0));
+
+    EXPECT_CALL(GetMock<AppCommonMock>(),
+        app_get_id(_)).WillRepeatedly(Invoke(__app_get_id_fake));
+
+    EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
+        Run(_, _)).WillOnce(Invoke(this, &WidgetAppTest::__run_fake));
+
+    ret = widget_app_main(argc, argv, &callback, data);
+    bundle_free_exported_argv(argc, &argv);
+    EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+  }
 
-  widget_app_lifecycle_callback_s callback;
-  callback.create = __app_create_cb;
-  callback.terminate = __app_terminate_cb;
+  void PrepareContext(widget_instance_create_cb created_cb) {
+    PrepareTest([](void* user_data) -> widget_class_h {
+      widget_instance_lifecycle_callback_s lifecycle;
+      lifecycle.create = reinterpret_cast<widget_instance_create_cb>(user_data);
+      lifecycle.destroy = __instance_destroy_cb;
+      lifecycle.pause = __instance_pause_cb;
+      lifecycle.resume = __instance_resume_cb;
+      lifecycle.resize = __instance_resize_cb;
+      lifecycle.update = __instance_update_cb;
+      widget_class_h cls = widget_app_class_create(lifecycle, nullptr);
+      EXPECT_NE(cls, nullptr);
+      return cls;
+    }, reinterpret_cast<void*>(created_cb));
+  }
 
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(), ecore_wl2_display_disconnect(_)).
-       Times(1);
+  void __run_fake(int argc, char** argv) {
+    tizen_base::Bundle b;
+    auto* p = GetMock<MultiWindowBaseMock>().real_;
 
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(), ecore_wl2_shutdown()).
-       Times(1);
+    p->OnCreate();
 
-  EXPECT_CALL(GetMock<SystemInfoMock>(),
-      system_info_get_platform_bool(_, _)).
-          WillOnce(DoAll(
-                  SetArgPointee<1>(true),
-                  Return(0)));
+    b.Add("__WIDGET_WIDTH__", "320");
+    b.Add("__WIDGET_HEIGHT__", "320");
+    b.Add("__AUL_WIDGET_INSTANCE_ID__", "instance_id");
+    b.Add("__AUL_WIDGET_ID__", "test");
+    b.Add("__WIDGET_OP__", "create");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_init(_, _, _, _)).
-          WillOnce(Invoke(__appcore_multiwindow_base_init_fake));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "resize");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<AulMock>(),
-      aul_app_get_pkgid_bypid(_, _, _)).
-          WillOnce(Invoke(__aul_app_get_pkgid_bypid_fake));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "update");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<AppCommonMock>(), app_get_id(_)).
-          WillOnce(Invoke(__app_get_id_fake));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "destroy");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_find(_)).
-          WillRepeatedly(
-            Return(
-              (appcore_multiwindow_base_instance_h)calloc(1, sizeof(char))));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "resume");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_class(_)).
-          WillRepeatedly(
-            Return(&__cls));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "pause");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillRepeatedly(
-        Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "terminate");
+    p->OnControl(b);
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_exit(_)).Times(2);
+    b.Delete("__WIDGET_OP__");
+    b.Add("__WIDGET_OP__", "period");
+    p->OnControl(b);
 
-  ret = widget_app_main(argc, argv, &callback, nullptr);
-  bundle_free_exported_argv(argc, &argv);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
-}
+    p->OnTerminate();
+  }
+};
 
-TEST_F(WidgetAppTest, widget_app_exit) {
+TEST_F(WidgetAppTest, widget_app_exit_n) {
   int ret = widget_app_exit();
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
-}
-
-TEST_F(WidgetAppTest, widget_app_terminate_context) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-  int ret = widget_app_terminate_context(context);
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
-}
-
-bool __widget_context_cb(widget_context_h context, void *user_data) {
-  return true;
+  EXPECT_NE(ret, WIDGET_ERROR_NONE);
 }
 
-TEST_F(WidgetAppTest, widget_app_foreach_context) {
-  int ret = widget_app_foreach_context(__widget_context_cb, nullptr);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+TEST_F(WidgetAppTest, widget_app_exit) {
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        EXPECT_CALL(GetMock<AulMock>(),
+            aul_notify_exit()).WillRepeatedly(Return(0));
+        int ret = widget_app_exit();
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
-void __app_event_cb(app_event_info_h event_info, void *user_data) {
+TEST_F(WidgetAppTest, widget_app_main) {
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        EXPECT_CALL(GetMock<AulMock>(),
+            aul_notify_exit()).WillRepeatedly(Return(0));
+        widget_app_exit();
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_add_event_handler) {
@@ -308,7 +262,7 @@ TEST_F(WidgetAppTest, widget_app_add_event_handler) {
                   Return(0)));
   int ret = widget_app_add_event_handler(&handle, APP_EVENT_LOW_MEMORY,
       __app_event_cb, nullptr);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  EXPECT_EQ(ret, WIDGET_ERROR_NONE);
 }
 
 TEST_F(WidgetAppTest, widget_app_remove_event_handler) {
@@ -321,195 +275,158 @@ TEST_F(WidgetAppTest, widget_app_remove_event_handler) {
   int ret = widget_app_add_event_handler(&handle, APP_EVENT_LOW_MEMORY,
       __app_event_cb, nullptr);
   ret = widget_app_remove_event_handler(handle);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  EXPECT_EQ(ret, WIDGET_ERROR_NONE);
 }
 
-TEST_F(WidgetAppTest, widget_app_get_id) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_id(_)).
-          WillOnce(Return("test"));
-
-  const char *id = widget_app_get_id(context);
-  free(context);
-  EXPECT_STREQ(id, "test");
+TEST_F(WidgetAppTest, widget_app_terminate_context) {
+  PrepareContext([](widget_context_h context, bundle* content,
+      int w, int h, void* user_data) -> int {
+        int ret = widget_app_terminate_context(context);
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
-TEST_F(WidgetAppTest, widget_app_class_create) {
-  widget_instance_lifecycle_callback_s lifecycle;
+TEST_F(WidgetAppTest, widget_app_foreach_context) {
+  PrepareTest([](void* user_data) -> widget_class_h {
+    widget_instance_lifecycle_callback_s lifecycle;
+    lifecycle.create = __instance_create_cb;
+    lifecycle.destroy = __instance_destroy_cb;
+    lifecycle.pause = __instance_pause_cb;
+    lifecycle.resume = __instance_resume_cb;
+    lifecycle.resize = __instance_resize_cb;
+    lifecycle.update = __instance_update_cb;
 
-  lifecycle.create = __instance_create_cb;
-  lifecycle.destroy = __instance_destroy_cb;
-  lifecycle.pause = __instance_pause_cb;
-  lifecycle.resume = __instance_resume_cb;
-  lifecycle.resize = __instance_resize_cb;
-  lifecycle.update = __instance_update_cb;
+    widget_class_h cls = widget_app_class_create(lifecycle, nullptr);
+    EXPECT_NE(cls, nullptr);
 
-  EXPECT_CALL(GetMock<AppCommonMock>(), app_get_id(_)).
-          WillOnce(Invoke(__app_get_id_fake));
+    int ret = widget_app_foreach_context(__widget_context_cb, nullptr);
+    EXPECT_EQ(ret, WIDGET_ERROR_NONE);
 
-  widget_class_h cls = widget_app_class_create(lifecycle, nullptr);
-  EXPECT_NE(nullptr, cls);
+    return cls;
+  }, nullptr);
 }
 
-TEST_F(WidgetAppTest, widget_app_context_set_tag) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
+TEST_F(WidgetAppTest, widget_app_get_id) {
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        const char *id = widget_app_get_id(context);
+        EXPECT_STREQ(id, "instance_id");
+        return 0;
+      });
+}
 
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
+TEST_F(WidgetAppTest, widget_app_class_create) {
+  PrepareContext(__instance_create_cb);
+}
 
-  int ret = widget_app_context_set_tag(context, (void*)"test");
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+TEST_F(WidgetAppTest, widget_app_context_set_tag) {
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        int ret = widget_app_context_set_tag(context,
+            reinterpret_cast<void*>(const_cast<char*>("test")));
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_context_get_tag) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
-
-  void* tag;
-  int ret = widget_app_context_get_tag(context, &tag);
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        int ret = widget_app_context_set_tag(context,
+            reinterpret_cast<void*>(const_cast<char*>("test")));
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        void* tag = nullptr;
+        ret = widget_app_context_get_tag(context, &tag);
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_context_set_content_info) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_id(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_instance_get_id_fake));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_class_id(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_instance_get_class_id_fake));
-
-  bundle* content_info = bundle_create();
-  int ret = widget_app_context_set_content_info(context, content_info);
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        bundle* content_info = bundle_create();
+        EXPECT_NE(content_info, nullptr);
+        int ret = widget_app_context_set_content_info(context, content_info);
+        bundle_free(content_info);
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_context_set_title) {
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
-
-  int ret = widget_app_context_set_title(context, "title");
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        int ret = widget_app_context_set_title(context, "title");
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_class_add) {
-  widget_instance_lifecycle_callback_s lifecycle;
-  lifecycle.create = __instance_create_cb;
-  lifecycle.destroy = __instance_destroy_cb;
-  lifecycle.pause = __instance_pause_cb;
-  lifecycle.resume = __instance_resume_cb;
-  lifecycle.resize = __instance_resize_cb;
-  lifecycle.update = __instance_update_cb;
-
-  widget_class_h cls = widget_app_class_add(
-      nullptr, "test", lifecycle, nullptr);
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_class_add(_)).
-      WillOnce(Invoke(__appcore_multiwindow_base_class_add_fake));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_class_id(_)).
-      WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_class_id_fake));
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_drop(_)).
-      Times(1);
-
-  cls = widget_app_class_add(
-      nullptr, "test", lifecycle, nullptr);
-  EXPECT_NE(nullptr, cls);
-
-  tizen_base::Bundle b;
-  b.Add("__AUL_WIDGET_VIEWER__", "test");
-  int ret = bundle_add_str(b.GetHandle(), "KEY", "VALUE");
-  ASSERT_EQ(ret, BUNDLE_ERROR_NONE);
-
-  char** argv = nullptr;
-  int argc = bundle_export_to_argv(b.GetHandle(), &argv);
-  ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE);
-  ASSERT_NE(argv, nullptr);
-  ASSERT_NE(argc, 0);
-
-  widget_app_lifecycle_callback_s callback;
-  callback.create = __app_create_cb;
-  callback.terminate = __app_terminate_cb;
-
-  ret = widget_app_main(argc, argv, &callback, nullptr);
-  bundle_free_exported_argv(argc, &argv);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  PrepareTest(
+      [](void* user_data) -> widget_class_h {
+        widget_instance_lifecycle_callback_s lifecycle;
+        lifecycle.create = __instance_create_cb;
+        lifecycle.destroy = __instance_destroy_cb;
+        lifecycle.pause = __instance_pause_cb;
+        lifecycle.resume = __instance_resume_cb;
+        lifecycle.resize = __instance_resize_cb;
+        lifecycle.update = __instance_update_cb;
+
+        widget_class_h cls = widget_app_class_add(
+            nullptr, "test", lifecycle, nullptr);
+        EXPECT_NE(cls, nullptr);
+        return cls;
+    }, nullptr);
 }
 
 TEST_F(WidgetAppTest, widget_app_get_elm_win_negative) {
-  Evas_Object* win;
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-  int ret = widget_app_get_elm_win(context, &win);
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_FAULT, ret);
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        Evas_Object* win = nullptr;
+        int ret = widget_app_get_elm_win(context, &win);
+        EXPECT_EQ(ret, WIDGET_ERROR_FAULT);
+        return 0;
+      });
 }
 
 TEST_F(WidgetAppTest, widget_app_get_elm_win) {
-  EXPECT_CALL(GetMock<ElmMock>(),
-      elm_win_add(_, _, _)).
-      WillOnce(Return((Evas_Object*)calloc(1, sizeof(char))));
-
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(),
-      ecore_evas_wayland2_window_get(_)).
-      WillOnce(Return((Ecore_Wl2_Window*)calloc(1, sizeof(char))));
-
-  EXPECT_CALL(GetMock<ElmMock>(),
-      elm_win_aux_hint_add(_, _, _)).
-      WillOnce(Return(0));
-
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(),
-      ecore_wl2_window_surface_get(_)).
-      WillOnce(Return(nullptr));
-
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(),
-      evas_object_event_callback_add(_, _, _, _)).
-      Times(1);
-
-  EXPECT_CALL(GetMock<EcoreWl2Mock>(),
-      evas_object_data_set(_, _, _)).
-      Times(1);
-
-  EXPECT_CALL(GetMock<MultiWindowBaseMock>(),
-      appcore_multiwindow_base_instance_get_extra(_)).
-      WillRepeatedly(Invoke(__appcore_multiwindow_base_instance_get_extra_fake));
-
-  Evas_Object* win;
-  widget_context_h context =
-      (widget_context_h)calloc(1, sizeof(struct _widget_context));
-  int ret = widget_app_get_elm_win(context, &win);
-  free(context);
-  EXPECT_EQ(WIDGET_ERROR_NONE, ret);
+  PrepareContext(
+      [](widget_context_h context, bundle* content,
+          int w, int h, void* user_data) -> int {
+        EXPECT_CALL(GetMock<ElmMock>(),
+            elm_win_add(_, _, _)).
+                WillOnce(Return(reinterpret_cast<Evas_Object*>(
+                    calloc(1, sizeof(char)))));
+
+        EXPECT_CALL(GetMock<EcoreWl2Mock>(),
+            ecore_evas_wayland2_window_get(_)).
+                WillOnce(Return(reinterpret_cast<Ecore_Wl2_Window*>(
+                    calloc(1, sizeof(char)))));
+
+        EXPECT_CALL(GetMock<ElmMock>(),
+            elm_win_aux_hint_add(_, _, _)).WillOnce(Return(0));
+
+        EXPECT_CALL(GetMock<EcoreWl2Mock>(),
+            ecore_wl2_window_surface_get(_)).WillOnce(Return(nullptr));
+
+        EXPECT_CALL(GetMock<EcoreWl2Mock>(),
+            evas_object_event_callback_add(_, _, _, _)).Times(1);
+
+        EXPECT_CALL(GetMock<EcoreWl2Mock>(),
+            evas_object_data_set(_, _, _)).Times(1);
+
+        Evas_Object* win = nullptr;
+        int ret = widget_app_get_elm_win(context, &win);
+        EXPECT_EQ(ret, WIDGET_ERROR_NONE);
+        return -1;
+      });
 }
index b41c2495bddc7c580aa6bb45d8e59e4dca9902be..8d5fca52b362737d842c8e6137fe088261fed8bc 100644 (file)
  */
 
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
 #include <widget_app.hpp>
 
-namespace {
+#include "include/widget_app.h"
+#include "include/widget_app_efl.h"
+#include "unit_tests/mock/app_common_mock.h"
+#include "unit_tests/mock/appcore_multiwindow_base_mock.h"
+#include "unit_tests/mock/aul_mock.h"
+#include "unit_tests/mock/ecore_wl2_mock.h"
+#include "unit_tests/mock/elm_mock.h"
+#include "unit_tests/mock/gio_mock.h"
+#include "unit_tests/mock/system_info_mock.h"
+#include "unit_tests/mock/test_fixture.h"
+#include "unit_tests/mock/widget_service_mock.h"
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class Mocks : public ::testing::NiceMock<GioMock>,
+              public ::testing::NiceMock<MultiWindowBaseMock>,
+              public ::testing::NiceMock<AppCommonMock>,
+              public ::testing::NiceMock<WidgetServiceMock>,
+              public ::testing::NiceMock<ElmMock>,
+              public ::testing::NiceMock<AulMock>,
+              public ::testing::NiceMock<SystemInfoMock>,
+              public ::testing::NiceMock<EcoreWl2Mock> {};
+
+class WidgetAppCppTest : public TestFixture {
+ public:
+  WidgetAppCppTest() : TestFixture(std::make_unique<Mocks>()) {}
+};
 
 class WidgetApp : public tizen_appfw::WidgetAppBase {
  public:
@@ -30,7 +62,7 @@ class WidgetApp : public tizen_appfw::WidgetAppBase {
       }
     };
 
-    Instance(widget_context_h h) : InstanceBase(h) {}
+    explicit Instance(widget_context_h h) : InstanceBase(h) {}
     void OnCreate(const tizen_base::Bundle& content, int w, int h) override {}
     void OnDestroy(DestroyType reason, tizen_base::Bundle* content) override {}
     void OnPause() override {}
@@ -44,13 +76,15 @@ class WidgetApp : public tizen_appfw::WidgetAppBase {
   void OnTerminate() override {}
 };
 
-}  // namespace
+TEST_F(WidgetAppCppTest, Run_InvalidParameter) {
+    EXPECT_CALL(GetMock<SystemInfoMock>(),
+        system_info_get_platform_bool(_, _)).
+            WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(0)));
 
-TEST(WidgetAppCppTest, Run_InvalidParameter) {
   WidgetApp app;
   std::unique_ptr<tizen_appfw::WidgetAppBase::InstanceBase::Factory> factory(
       new WidgetApp::Instance::Factory());
 
   int ret = app.Run(0, nullptr, std::move(factory));
   EXPECT_EQ(ret, APP_ERROR_INVALID_PARAMETER);
-}
\ No newline at end of file
+}