Add plugin for string type support size type 83/293583/29
authorSukhyungKang <shine.kang@samsung.com>
Wed, 31 May 2023 09:41:53 +0000 (18:41 +0900)
committerSukhyungKang <shine.kang@samsung.com>
Fri, 9 Aug 2024 04:17:50 +0000 (13:17 +0900)
Change-Id: I5f3684d58a35293b88269331cb41eae390115c17
Signed-off-by: SukhyungKang <shine.kang@samsung.com>
15 files changed:
include/widget_service_internal.h
parser/installer_plugin/widget_plugin_parser_pkgmgr_interface.cc
parser/lib/widget_info.cc
parser/lib/widget_info.hh
parser/lib/widget_plugin_parser.cc
parser/lib/widget_plugin_parser_db.cc
scripts/505.widget_service_upgrade.sh
src/CMakeLists.txt
src/widget_service.c
src/widget_service_internal.cc [new file with mode: 0644]
src/widget_service_manager.cc [new file with mode: 0644]
src/widget_service_manager.hh [new file with mode: 0644]
src/widget_service_plugin_private.cc [new file with mode: 0644]
src/widget_service_plugin_private.hh [new file with mode: 0644]
tool/widget_test.c

index 061d091fb588202465c60ed4ae1c659e889dbcec..3c8ed26b2cd0e52a8ffe831e9402cd32a0be81a1 100644 (file)
@@ -359,6 +359,22 @@ typedef struct widget_text_signal {
        } geometry;                 /**< Region information of this text signal */
 } *widget_text_signal_s;
 
+/**
+ * @internal
+ * @brief widget support size info
+ * @since_tizen 9.0
+ */
+typedef void *widget_supported_size_info_h;
+
+/**
+ * @internal
+ * @brief Called to get support size info
+ * @since_tizen 9.0
+ * @param[in] info The information of supported widget size
+ * @param[in] user_data The user data passed from the callback registration function
+ */
+typedef bool (*widget_service_supported_size_info_cb)(widget_supported_size_info_h info, void *user_data);
+
 /**
  * @internal
  * @brief Gets the name of the provider (provider name == widget appid), you have to release the return value after use it.
@@ -784,6 +800,86 @@ extern int widget_service_get_hw_accelerated(const char *widget_id);
 extern int widget_service_set_sdk_util(bundle *data);
 extern int widget_service_check_db_integrity(bool is_init);
 
+/**
+ * @brief Getting size type for width and height
+ * @since_tizen 9.0
+ * @privlevel public
+ * @privlege %http://tizen.org/privilege/widget.viewer
+ * @param[in] width width of widget
+ * @param[in] height height of widget
+ * @param[out] size_type size type of widget
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_get_size_type_from_size(int width, int height, char **size_type);
+
+/**
+ * @brief Getting width and height for size type
+ * @since_tizen 9.0
+ * @privlege %http://tizen.org/privilege/widget.viewer
+ * @privlevel public
+ * @param[in] size_type size type of widget
+ * @param[out] width width of widget
+ * @param[out] height height of widget
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_get_size_from_size_type(const char *size_type, int *width, int *height);
+
+/**
+ * @brief Getting preview image path
+ * @since_tizen 9.0
+ * @privlevel public
+ * @privlege %http://tizen.org/privilege/widget.viewer
+ * @param[in] widget_id id of widget
+ * @param[in] size_type size type of widget
+ * @return path of preview image
+ */
+char *widget_service_get_preview_path_from_widget_id(const char *widget_id, const char *size_type);
+
+/**
+ * @brief Call callback function for each supported sizes
+ * @since_tizen 9.0
+ * @privlevel public
+ * @privlege %http://tizen.org/privilege/widget.viewer
+ * @param[in] widget_id id of widget
+ * @param[in] callback callback function
+ * @param[in] size_type size type of widget
+ * @param[in] user_data user data
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_foreach_supported_sizes(const char *widget_id,
+       widget_service_supported_size_info_cb callback, void *user_data);
+
+/**
+ * @brief Getting preview image path from supported size info handle
+ * @since_tizen 9.0
+ * @param[in] info handle for supported size
+ * @param[out] preview_path path of preview image
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_supported_size_info_get_preview_path(
+       widget_supported_size_info_h info, const char **preview_path);
+
+/**
+ * @brief Getting type from supported size info handle
+ * @since_tizen 9.0
+ * @param[in] info handle for supported size
+ * @param[out] size_type size type of widget
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_supported_size_info_get_type(
+       widget_supported_size_info_h info, const char **size_type);
+
+/**
+ * @brief Getting width and height from supported size info handle
+ * @since_tizen 9.0
+ * @param[in] info handle for supported size
+ * @param[out] width width of widget
+ * @param[out] height height of widget
+ * @return 0 on success, otherwise a negative error value
+ */
+int widget_service_supported_size_info_get_size(
+       widget_supported_size_info_h info, int *width, int *height);
+
 #ifdef __cplusplus
 }
 #endif
index 616742a0e1d38043837ca4e228c4fd5649cad76d..9627b91e851b0fa9e021c49a1fce25636314f498 100644 (file)
@@ -34,7 +34,7 @@ using namespace widget_service::parser;
 namespace {
 
 constexpr const char PLUGIN_PATH[] =
-    "/usr/share/widget-service/plugin/widget-service-parser-plugin.so";
+    "/usr/share/widget_service/plugin/widget_service_plugin.so";
 
 struct DlCloser {
   void operator()(void* handle) const {
@@ -45,10 +45,7 @@ struct DlCloser {
 std::unique_ptr<void, DlCloser> g_plugin;
 
 IWidgetPluginParser* LoadPlugin() {
-  static IWidgetPluginParser* parser;
-
-  if (parser)
-    return parser;
+  IWidgetPluginParser* parser;
 
   if (access(PLUGIN_PATH, F_OK) == -1) {
     LOGD("%s does not exist", PLUGIN_PATH);
@@ -72,14 +69,14 @@ IWidgetPluginParser* LoadPlugin() {
 
   parser = get_mod();
 
-  return parser;
+  return std::move(parser);
 }
 
 IWidgetPluginParser* GetPlugin() {
   auto* ret = LoadPlugin();
 
   if (ret)
-    return ret;
+    return std::move(ret);
 
   return new WidgetPluginParser();
 }
index 424b7c9180ce1d7eedb1d75d34d79a3a5a9a4c3d..0025a6f63ff81e23ec75eba43dd669d4cec74ff4 100644 (file)
@@ -20,9 +20,9 @@
 namespace widget_service::parser {
 
 WidgetInfo::SupportSize::SupportSize(std::string preview, bool frame,
-    int width, int height)
+    int width, int height, std::string support_type)
     : preview_(std::move(preview)), frame_(frame), width_(width),
-      height_(height) {
+      height_(height), support_type_(std::move(support_type)) {
 }
 
 const std::string& WidgetInfo::SupportSize::GetPreview() const {
@@ -41,6 +41,10 @@ int WidgetInfo::SupportSize::GetHeight() const {
   return height_;
 }
 
+const std::string& WidgetInfo::SupportSize::GetSupportType() const {
+  return support_type_;
+}
+
 WidgetInfo::Label::Label(std::string label, std::string lang)
     : label_(std::move(label)), lang_(std::move(lang)) {
 }
index dc0772d2dba376b3ec5eebf47b6765d89f188180..f64321c14a9a7485fd1aba2e82bb64aa153b544e 100644 (file)
@@ -30,18 +30,21 @@ class EXPORT_API WidgetInfo {
   class SupportSize {
    public:
     SupportSize() = default;
-    SupportSize(std::string preview, bool frame, int width, int height);
+    SupportSize(std::string preview, bool frame,
+        int width, int height, std::string support_type);
 
     const std::string& GetPreview() const;
     bool IsFrame() const;
     int GetWidth() const;
     int GetHeight() const;
+    const std::string& GetSupportType() const;
 
    private:
     std::string preview_;
     bool frame_ = false;
     int width_ = 0;
     int height_ = 0;
+    std::string support_type_;
   };
 
   class Label {
index 305641469e5646954fd7cea04460e282380ee1f4..a6a73df71c7fc5381c9fc0a173a480d64f8599d9 100644 (file)
@@ -334,7 +334,7 @@ int WidgetPluginParser::ParseSupportSize(xmlNode* node,
   if (!attr.empty() && !strcasecmp(attr.c_str(), "true"))
     frame = true;
 
-  sizes.emplace_back(std::move(preview), frame, width, height);
+  sizes.emplace_back(std::move(preview), frame, width, height, "");
 
   return 0;
 }
index bf8d81633f77c34f05834ef21d07f6fa29b01975..71b1d486b9978e6ca586126665db3aba2e27b41e 100644 (file)
@@ -33,7 +33,7 @@ namespace {
 
 int target_uid_initialized;
 uid_t target_uid;
-int root_path_initialized;
+std::string _initialized_pkgid;
 std::string root_path;
 
 uid_t GetTargetUid() {
@@ -55,7 +55,7 @@ const std::string& GetRootPath(const char* pkgid) {
   uid_t uid = GetTargetUid();
   static std::string empty;
 
-  if (root_path_initialized)
+  if (!_initialized_pkgid.empty() && !_initialized_pkgid.compare(pkgid))
     return root_path;
 
   int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &pkginfo);
@@ -73,7 +73,7 @@ const std::string& GetRootPath(const char* pkgid) {
 
   root_path =  path ? path : "./";
   pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
-  root_path_initialized = 1;
+  _initialized_pkgid = pkgid;
 
   return root_path;
 }
@@ -251,14 +251,15 @@ int WidgetPluginParser::Impl::InsertSupportSize(const tizen_base::Database& db,
   for (const auto& i : sizes) {
     auto q = std::move(tizen_base::Database::Sql(
         "INSERT OR REPLACE INTO support_size "
-        "(classid, preview, frame, width, height) "
-        "VALUES (?, ?, ?, ?, ?)")
+        "(classid, preview, frame, width, height, support_type) "
+        "VALUES (?, ?, ?, ?, ?, ?)")
         .SetEmptyStringAsNull(true)
         .Bind(classid)
         .Bind(ConvertPath(i.GetPreview(), pkgid))
         .Bind(i.IsFrame() ? 1 : 0)
         .Bind(i.GetWidth())
-        .Bind(i.GetHeight()));
+        .Bind(i.GetHeight())
+        .Bind(i.GetSupportType()));
     auto r = db.Exec(q);
     if (!static_cast<bool>(r))
       return -1;
index 55a3255264981385c2e0a8c95e3682f1a914ce9d..c11a596d81988d66336ba2b8b9c0a10c607ce4c4 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #------------------------------------------#
-# widget service patch for upgrade (4.0 -> 5.x) #
+# widget service patch for upgrade         #
 #------------------------------------------#
 
 # Macro
@@ -11,18 +11,46 @@ DB_WIDGET_SERVICE=/opt/dbspace/.widget.db
 DB_ETC_WIDGET_SERVICE=/opt/etc/skel/.applications/dbspace/.widget.db
 DB_USER_WIDGET_SERVICE=/opt/usr/home/owner/.applications/dbspace/.widget.db
 
-function add_disable_cloumn(){
-       echo "PRAGMA user_version = 50;
-               BEGIN EXCLUSIVE TRANSACTION;
-               ALTER TABLE widget_class ADD COLUMN is_disable INTEGER DEFAULT 0;
-               COMMIT TRANSACTION;" |
-       sqlite3 $1
+UpdateTable() {
+  echo "## UpdateTable $1"
+
+  DISABLE_COLUMN=`sqlite3 $1 'PRAGMA table_info(widget_class)' | grep is_disable`
+  TYPE_COLUMN=`sqlite3 $1 'PRAGMA table_info(support_size)' | grep support_type`
+
+  if [ -z "${DISABLE_COLUMN}" ]; then
+    echo "is_diable not exist"
+
+    echo "BEGIN EXCLUSIVE TRANSACTION;
+      ALTER TABLE widget_class ADD COLUMN is_disable INTEGER DEFAULT 0;
+      COMMIT TRANSACTION;" |
+    sqlite3 $1
+  else
+       echo "is_disable exist"
+  fi
+
+  if [ -z "${TYPE_COLUMN}" ]; then
+    echo "support_type not exist"
+
+    echo "BEGIN EXCLUSIVE TRANSACTION;
+      ALTER TABLE support_size ADD COLUMN support_type TEXT;
+      COMMIT TRANSACTION;" |
+    sqlite3 $1
+  else
+       echo "support_type exist"
+  fi
+
+}
+
+UpdateDB() {
+echo "## UpdateDB"
+
+UpdateTable $DB_WIDGET_SERVICE
+UpdateTable $DB_ETC_WIDGET_SERVICE
+UpdateTable $DB_USER_WIDGET_SERVICE
 }
 
-# Add column
-add_disable_cloumn $DB_WIDGET_SERVICE
-add_disable_cloumn $DB_ETC_WIDGET_SERVICE
-add_disable_cloumn $DB_USER_WIDGET_SERVICE
+UpdatePermission() {
+echo "## UpdatePermission"
 
 # Adjust Permission
 chsmack -a User::Home $DB_WIDGET_SERVICE
@@ -42,3 +70,15 @@ chmod 666 $DB_USER_WIDGET_SERVICE-journal
 
 chmod 666 $DB_ETC_WIDGET_SERVICE
 chmod 666 $DB_ETC_WIDGET_SERVICE-journal
+}
+
+UpdateWidgetDB() {
+
+echo "## update widget db"
+
+UpdateDB
+UpdatePermission
+
+}
+
+UpdateWidgetDB
index 39f272b8e0dc76bcbc9c26af8f0da360cee73069..d830c6e14b4f8e3d4c2d1a2a9f9d92821b4057fb 100644 (file)
@@ -2,7 +2,7 @@ ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
 ADD_DEFINITIONS("-DLOG_TAG=\"WIDGET_SERVICE\"")
 ADD_DEFINITIONS("-DNDEBUG")
 ADD_DEFINITIONS("-D_USE_ECORE_TIME_GET")
-ADD_DEFINITIONS("-DRESOLUTION_FILE=\"/usr/share/widget-service/resolution.ini\"")
+ADD_DEFINITIONS("-DRESOLUTION_FILE=\"/usr/share/widget_service/resolution.ini\"")
 
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} LIB_SRCS)
 
@@ -15,8 +15,11 @@ SET_TARGET_PROPERTIES(${TARGET_WIDGET_SERVICE} PROPERTIES COMPILE_FLAGS
   ${CFLAGS} "-fpic")
 SET_TARGET_PROPERTIES(${TARGET_WIDGET_SERVICE} PROPERTIES LINK_FLAGS "-ldl -lpthread")
 
+TARGET_LINK_LIBRARIES(${TARGET_WIDGET_SERVICE} PRIVATE ${TARGET_WIDGET_PARSER} "-ldl")
+
 TARGET_INCLUDE_DIRECTORIES(${TARGET_WIDGET_SERVICE} PUBLIC
-  ${CMAKE_CURRENT_SOURCE_DIR}/../include)
+  ${CMAKE_CURRENT_SOURCE_DIR}/../include
+  ${CMAKE_CURRENT_SOURCE_DIR}/../parser/lib)
 
 APPLY_PKG_CONFIG(${TARGET_WIDGET_SERVICE} PUBLIC
   DLOG_DEPS
@@ -37,6 +40,7 @@ APPLY_PKG_CONFIG(${TARGET_WIDGET_SERVICE} PUBLIC
   CYNARA_CLIENT_DEPS
   INIPARSER_DEPS
   SMACK_DEPS
+  DATABASE_DEPS
 )
 
 INSTALL(TARGETS ${TARGET_WIDGET_SERVICE} DESTINATION ${LIB_INSTALL_DIR})
@@ -49,6 +53,8 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../include/widget_service.h DESTINATIO
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../include/widget_service_internal.h DESTINATION include/${PROJECT_NAME})
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../include/widget_errno.h DESTINATION include/${PROJECT_NAME})
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../include/widget_instance.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/widget_service_manager.hh DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/widget_service_plugin_private.hh DESTINATION include/${PROJECT_NAME})
 
 INSTALL(FILES ${CMAKE_SOURCE_DIR}/data/wayland.mobile.resolution.ini DESTINATION /usr/share/${PROJECT_NAME} RENAME "mobile.resolution.ini" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
 INSTALL(FILES ${CMAKE_SOURCE_DIR}/data/wayland.wearable.resolution.ini DESTINATION /usr/share/${PROJECT_NAME} RENAME "wearable.resolution.ini" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
index e7a8829ed49263671db5e08bdf5059ef728d4bfd..9bf6bfca50cfacf1a6b90e9696a0a945ebb2a26f 100644 (file)
@@ -76,11 +76,12 @@ CREATE TABLE widget_class ( \
        PRIMARY KEY(classid) \
 ); \
 CREATE TABLE support_size ( \
-       classid TEXT NOT NULL, \
-       preview TEXT NOT NULL, \
-       frame   INTEGER DEFAULT 0, \
-       width   INTEGER NOT NULL, \
-       height  INTEGER NOT NULL, \
+       classid      TEXT NOT NULL, \
+       preview      TEXT NOT NULL, \
+       frame        INTEGER DEFAULT 0, \
+       width        INTEGER NOT NULL, \
+       height       INTEGER NOT NULL, \
+       support_type TEXT, \
        FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE \
 ); \
 CREATE TABLE label ( \
@@ -1796,7 +1797,7 @@ static int update_lang_info(void)
 
        syslang = vconf_get_str(VCONFKEY_LANGSET);
        if (!syslang) {
-               ErrPrint("Failed to get vconf-lang");
+               _E("Failed to get vconf-lang");
                return -EFAULT;
        }
 
diff --git a/src/widget_service_internal.cc b/src/widget_service_internal.cc
new file mode 100644 (file)
index 0000000..d4e7b71
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2024 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 "widget_service_internal.h"
+
+#include <linux/limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <dlog.h>
+#include <tzplatform_config.h>
+#include <database.hpp>
+
+#include "debug.h"
+#include "widget_errno.h"
+#include "widget_service_manager.hh"
+#include "widget_info.hh"
+#include "widget_plugin_parser.hh"
+
+#define GLOBALAPP_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+
+using namespace widget_service;
+using namespace widget_service::parser;
+using tizen_base::_;
+
+namespace {
+
+bool BusyHandler(int count) {
+  constexpr int BUSY_WAITING_USEC = 50000;
+  constexpr int BUSY_WAITING_MAX = 20;
+
+  if (count < BUSY_WAITING_MAX) {
+    usleep(BUSY_WAITING_USEC);
+    return true;
+  }
+
+  return false;
+}
+
+int IsGlobal(uid_t uid) {
+  constexpr int ROOT_USER = 0;
+
+  if (uid == ROOT_USER || uid == GLOBALAPP_USER)
+    return 1;
+  else
+    return 0;
+}
+
+const char* GetDbPath(uid_t uid) {
+  if (!IsGlobal(uid))
+    tzplatform_set_user(uid);
+
+  const char* path = tzplatform_mkpath(IsGlobal(uid) ?
+      TZ_SYS_DB : TZ_USER_DB, ".widget.db");
+
+  tzplatform_reset_user();
+
+  return path;
+}
+
+std::string GetPreviewPath(std::string widget_id,
+        std::string size_type, uid_t uid) {
+  std::string path = GetDbPath(uid);
+  std::string preview_path;
+
+  if (access(path.c_str(), F_OK) == -1) {
+    LOGD("db(%s) does not exist, create one", path.c_str());
+    return "";
+  }
+
+  try {
+    tizen_base::Database db(path, SQLITE_OPEN_READONLY, BusyHandler);
+
+    auto q = tizen_base::Database::Sql(
+        "SELECT preview FROM support_size WHERE "
+        "classid=? AND support_type=?")
+        .SetEmptyStringAsNull(true)
+        .Bind(widget_id)
+        .Bind(size_type);
+    tizen_base::Database::Result r = db.Exec(q);
+    for (const auto& i : r) {
+        preview_path = static_cast<std::string>(i.Get(0));
+    }
+
+  } catch (const tizen_base::DbException& e) {
+    LOGE("Catch : %s", e.msg());
+    throw std::exception();
+  }
+
+  return preview_path;
+}
+
+std::vector<WidgetInfo::SupportSize> GetSupportedSizes(
+    uid_t uid, std::string widget_id) {
+  std::string path = GetDbPath(uid);
+  std::vector<WidgetInfo::SupportSize> sizes;
+
+  if (access(path.c_str(), F_OK) == -1) {
+    LOGD("db(%s) does not exist, create one", path.c_str());
+    throw std::exception();
+  }
+
+  try {
+    tizen_base::Database db(path, SQLITE_OPEN_READONLY, BusyHandler);
+
+    auto q = tizen_base::Database::Sql(
+        "SELECT * FROM support_size WHERE classid=?")
+        .SetEmptyStringAsNull(true)
+        .Bind(widget_id);
+    tizen_base::Database::Result r = db.Exec(q);
+    for (const auto& i : r) {
+        auto [classid, preview, frame, width, height, support_type] =
+            i.Get<_, _, _, _, _, _>();
+
+        auto[w, h] = WidgetServiceManager::GetInst().GetSize(
+            static_cast<std::string>(support_type));
+
+        sizes.push_back(
+          WidgetInfo::SupportSize(static_cast<std::string>(preview),
+              static_cast<int>(frame), w, h, static_cast<std::string>(support_type)));
+    }
+  } catch (const tizen_base::DbException& e) {
+    LOGE("DB exception Catch : %s", e.msg());
+    throw std::exception();
+  }
+
+  return sizes;
+}
+
+}  // namespace
+
+extern "C" EAPI int widget_service_get_size_type_from_size (int width, int height,
+    char **size_type) {
+  try {
+    if (!WidgetServiceManager::GetInst().GetFeatureEnabled()) {
+      LOGE("not supported");
+      return WIDGET_ERROR_NOT_SUPPORTED;
+    }
+
+    if (width <= 0 || height <= 0 || size_type == nullptr) {
+      LOGE("invalid parameter");
+      return WIDGET_ERROR_INVALID_PARAMETER;
+    }
+
+    std::string type_str = WidgetServiceManager::GetInst().GetType(width, height);
+
+    if (type_str.empty()) {
+      LOGE("Failed to get type");
+      return WIDGET_ERROR_NOT_EXIST;
+    }
+
+    *size_type = strdup(type_str.c_str());
+  } catch (const std::exception& e) {
+    LOGE("Failed to get size type ex");
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+extern "C" EAPI int widget_service_get_size_from_size_type (const char *size_type,
+    int *width, int *height) {
+  try {
+    if (!WidgetServiceManager::GetInst().GetFeatureEnabled()) {
+      LOGE("not supported");
+      return WIDGET_ERROR_NOT_SUPPORTED;
+    }
+
+    if (size_type == nullptr || width == nullptr || height == nullptr) {
+      LOGE("invalid parameter");
+      return WIDGET_ERROR_INVALID_PARAMETER;
+    }
+
+    auto[w, h] = WidgetServiceManager::GetInst().GetSize(size_type);
+
+    *width = w;
+    *height = h;
+  } catch (const std::exception& e) {
+    LOGE("Failed to get size ex");
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+extern "C" EAPI char *widget_service_get_preview_path_from_widget_id(
+    const char *widget_id, const char *size_type) {
+  std::string path;
+  std::string lang_path;
+  std::string preview_path;
+  char* ret = nullptr;
+
+  try {
+    if (!WidgetServiceManager::GetInst().GetFeatureEnabled()) {
+      LOGE("not supported");
+      set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
+      return nullptr;
+    }
+
+    if (WidgetServiceManager::GetInst().CheckPrivilege(
+            "http://tizen.org/privilege/widget.viewer") < 0) {
+      LOGE("permission denied");
+      set_last_result(WIDGET_ERROR_PERMISSION_DENIED);
+      return nullptr;
+    }
+  } catch (const std::exception& e) {
+    LOGE("Failed to get preview image path");
+    return nullptr;
+  }
+
+  if (widget_id == nullptr) {
+    LOGE("invalid parameter");
+    set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+    return nullptr;
+  }
+
+  try {
+    path = GetPreviewPath(widget_id, size_type, getuid());
+  } catch (const std::exception& e) {
+    LOGE("get db exception");
+    set_last_result(WIDGET_ERROR_IO_ERROR);
+    return nullptr;
+  }
+
+  if (path.empty()) {
+    if (!IsGlobal(getuid())) {
+      try {
+        path = GetPreviewPath(widget_id, size_type, GLOBALAPP_USER);
+      } catch (const std::exception& e) {
+        LOGE("get db exception");
+        set_last_result(WIDGET_ERROR_IO_ERROR);
+        return nullptr;
+      }
+    }
+  }
+
+  if (path.empty()) {
+    LOGE("Can not find preview path");
+    set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
+    return nullptr;
+  }
+
+  try {
+    lang_path = WidgetServiceManager::GetInst().GetLangPath();
+    preview_path = lang_path + path;
+
+    if (access(preview_path.c_str(), R_OK) != 0) {
+      _D("Access failed: %s, %d", preview_path.c_str(), errno);
+      preview_path = path;
+    }
+  } catch (const std::exception& e) {
+    LOGE("failed to get lang path");
+    set_last_result(WIDGET_ERROR_IO_ERROR);
+    return nullptr;
+  }
+
+  ret = strdup(preview_path.c_str());
+
+  return ret;
+}
+
+extern "C" EAPI int widget_service_foreach_supported_sizes(
+    const char *widget_id, widget_service_supported_size_info_cb callback,
+    void *user_data) {
+  std::vector<WidgetInfo::SupportSize> sizes;
+
+  try {
+    if (!WidgetServiceManager::GetInst().GetFeatureEnabled()) {
+      LOGE("not supported");
+      return WIDGET_ERROR_NOT_SUPPORTED;
+    }
+
+    if (WidgetServiceManager::GetInst().CheckPrivilege(
+            "http://tizen.org/privilege/widget.viewer") < 0) {
+      LOGE("permission denied");
+      return WIDGET_ERROR_PERMISSION_DENIED;
+    }
+  } catch (const std::exception& e) {
+    LOGE("Failed to get supported size");
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  if (widget_id == nullptr || callback == nullptr) {
+    LOGE("invalid parameter");
+    return WIDGET_ERROR_INVALID_PARAMETER;
+  }
+
+  try {
+    sizes = GetSupportedSizes(getuid(), widget_id);
+  } catch (const std::exception& e) {
+    LOGE("get db exception");
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  if ((int)sizes.size() == 0) {
+    if (!IsGlobal(getuid())) {
+      try {
+        sizes = GetSupportedSizes(GLOBALAPP_USER, widget_id);
+      } catch (const std::exception& e) {
+        LOGE("get db exception");
+        return WIDGET_ERROR_IO_ERROR;
+      }
+    }
+  }
+
+  int count = (int)sizes.size();
+
+  if (count == 0) {
+    LOGE("sizes not exist, id : %s", widget_id);
+    return WIDGET_ERROR_NOT_EXIST;
+  }
+
+  for (int i = 0; i < count; i++) {
+    LOGW("call foreach callback");
+    if (!callback(static_cast<widget_supported_size_info_h>(&sizes[i]),
+        user_data)) {
+      LOGE("foreach callback error");
+      return WIDGET_ERROR_IO_ERROR;
+    }
+  }
+
+  return WIDGET_ERROR_NONE;
+}
+
+extern "C" EAPI int widget_service_supported_size_info_get_preview_path(
+    widget_supported_size_info_h info, const char **preview_path) {
+  if (info == nullptr || preview_path == nullptr)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  WidgetInfo::SupportSize *size = static_cast<WidgetInfo::SupportSize*>(info);
+
+  *preview_path = size->GetPreview().c_str();
+
+  return WIDGET_ERROR_NONE;
+}
+
+extern "C" EAPI int widget_service_supported_size_info_get_type(
+    widget_supported_size_info_h info, const char **size_type) {
+  if (info == nullptr || size_type == nullptr)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  WidgetInfo::SupportSize *size = static_cast<WidgetInfo::SupportSize*>(info);
+
+  *size_type = size->GetSupportType().c_str();
+
+  return WIDGET_ERROR_NONE;
+}
+
+extern "C" EAPI int widget_service_supported_size_info_get_size(
+    widget_supported_size_info_h info, int *width, int *height) {
+  if (info == nullptr)
+    return WIDGET_ERROR_INVALID_PARAMETER;
+
+  WidgetInfo::SupportSize *size = static_cast<WidgetInfo::SupportSize*>(info);
+
+  *width = size->GetWidth();
+  *height = size->GetHeight();
+
+  return WIDGET_ERROR_NONE;
+}
diff --git a/src/widget_service_manager.cc b/src/widget_service_manager.cc
new file mode 100644 (file)
index 0000000..b9616b0
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2024 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 "widget_service_manager.hh"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <iniparser.h>
+#include <sys/smack.h>
+#include <unicode/uloc.h>
+
+#include <exception>
+
+#include <dlog.h>
+#include <cynara-client.h>
+#include <system_info.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "widget_errno.h"
+#include "debug.h"
+#include "widget_instance.h"
+#include "widget_service.h"
+#include "widget_service_internal.h"
+
+namespace {
+
+constexpr const char kResolutionFilePath[] = "/usr/share/widget_service/";
+constexpr const char kResolutionFileName[] = "resolution.ini";
+constexpr const char kResolutionSectionName[] = "resolution";
+
+}  // namespace
+
+namespace widget_service {
+
+WidgetServiceManager::WidgetServiceManager() = default;
+WidgetServiceManager::~WidgetServiceManager() = default;
+
+WidgetServiceManager& WidgetServiceManager::GetInst() {
+  static WidgetServiceManager w_inst;
+  int ret;
+  if (!w_inst.is_initialized_) {
+    ret = w_inst.Init();
+    if (ret != WIDGET_ERROR_NONE) {
+      LOGE("Failed to init widget manager");
+      throw std::exception();
+    }
+  }
+
+  return w_inst;
+}
+
+std::string WidgetServiceManager::GetResolutionFilePath() {
+  int w = 0;
+  int h = 0;
+  int ret;
+
+  if (plugin_)
+     std::tie(w, h) = plugin_->GetScreenResolution();
+
+  if (w == 0 && h == 0) {
+    ret = system_info_get_platform_int(
+        "http://tizen.org/feature/screen.width", &w);
+
+    if (ret != SYSTEM_INFO_ERROR_NONE)
+      LOGE("fail to get width: %d", ret);
+
+    ret = system_info_get_platform_int(
+        "http://tizen.org/feature/screen.height", &h);
+
+    if (ret != SYSTEM_INFO_ERROR_NONE)
+      LOGE("fail to get height: %d", ret);
+  }
+  _D("screen size : %d %d", w, h);
+
+  std::string path = std::string(kResolutionFilePath) + std::to_string(w) + "x"
+          + std::to_string(h) + "/" + std::string(kResolutionFileName);
+
+  _D("Selected conf file: %s", path.c_str());
+  if (access(path.c_str(), F_OK) != 0) {
+    LOGE("Fallback to default, access: %d", errno);
+
+    path = std::string(kResolutionFilePath) + std::string(kResolutionFileName);
+    if (access(path.c_str(), F_OK) != 0) {
+      LOGE("Serious error - there is no conf file, use default setting: %d\n", errno);
+      path = "";
+    }
+  }
+
+  return path;
+}
+
+int WidgetServiceManager::SetResolutionFromFile() {
+  int width = 0;
+  int height = 0;
+  int i;
+  char** key_list;
+  int key_num;
+  dictionary* dic;
+  std::string type_str;
+  std::string key_str;
+  std::string size_str;
+  std::string file_path;
+
+  file_path = GetResolutionFilePath();
+  if (file_path.empty())
+    return WIDGET_ERROR_OUT_OF_MEMORY;
+
+  dic = iniparser_load(file_path.c_str());
+  if (dic == nullptr) {
+    LOGE("fail to load [%s] ", file_path.c_str());
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  key_num = iniparser_getsecnkeys(dic, kResolutionSectionName);
+  if (key_num == 0) {
+    LOGE("key_num is zero");
+    iniparser_freedict(dic);
+    return WIDGET_ERROR_NONE;
+  }
+
+  key_list = (char**)calloc(key_num, sizeof(char *));
+  if (key_list == nullptr) {
+    LOGE("Out of memory");
+    iniparser_freedict(dic);
+    return WIDGET_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!iniparser_getseckeys(dic, kResolutionSectionName,
+          (const char **)key_list)) {
+    LOGE("Failed to get section keys");
+    free(key_list);
+    iniparser_freedict(dic);
+    return WIDGET_ERROR_IO_ERROR;
+  }
+
+  for (i = 0; i < key_num; i++) {
+    // key_str >> resolution:1x1
+    // size_str >> 100x100
+
+    key_str = std::string(key_list[i]);
+
+    std::string::size_type pos = key_str.find(":");
+    if (std::string::npos == pos) {
+      LOGE("Invalid syntax: [%s]", key_str.c_str());
+      continue;
+    }
+
+    std::string type_str = key_str.substr(pos + 1);
+
+    size_str = std::string(iniparser_getstring(dic, key_str.c_str(), nullptr));
+    if (size_str.empty()) {
+      LOGE("size str is empty");
+      continue;
+    }
+
+    std::string::size_type sub_pos = size_str.find("x");
+    if (std::string::npos == sub_pos) {
+      LOGE("Invalid syntax: [%s]", size_str.c_str());
+      continue;
+    }
+    width = atoi(size_str.substr(0, sub_pos).c_str());
+    height = atoi(size_str.substr(sub_pos + 1).c_str());
+
+    support_size_map_.insert({type_str, {width, height}});
+  }
+
+  free(key_list);
+  iniparser_freedict(dic);
+
+  return WIDGET_ERROR_NONE;
+}
+
+std::string WidgetServiceManager::GetType(int width, int height) {
+  for (auto& support_size : support_size_map_) {
+    if (support_size.second.first == width &&
+        support_size.second.second == height)
+      return support_size.first;
+  }
+
+  return "";
+}
+
+std::tuple<int, int> WidgetServiceManager::GetSize(std::string size_type) {
+  int width = 0;
+  int height = 0;
+
+  width = support_size_map_[size_type].first;
+  height = support_size_map_[size_type].second;
+
+  return std::tuple<int, int>(width, height);
+}
+
+int WidgetServiceManager::UpdateLangInfo() {
+  char* syslang;
+  UErrorCode err;
+  int country_len;
+  char country[ULOC_COUNTRY_CAPACITY];
+
+  syslang = vconf_get_str(VCONFKEY_LANGSET);
+  if (!syslang) {
+    LOGE("Failed to get vconf-lang");
+    return -EFAULT;
+  }
+
+  if (!syslang_.empty() && syslang_.compare(syslang) == 0) {
+    LOGD("Syslang is not changed: %s", syslang);
+    free(syslang);
+    return 0;
+  }
+
+  syslang_ = syslang;
+  free(syslang);
+
+  err = U_ZERO_ERROR;
+  uloc_setDefault(syslang_.c_str(), &err);
+  if (!U_SUCCESS(err)) {
+    LOGE("Failed to set default lang: %s", u_errorName(err));
+    return -EFAULT;
+  }
+
+  iso3lang_ = uloc_getISO3Language(uloc_getDefault());
+  if (!iso3lang_.empty()) {
+    LOGE("Failed to get iso3lang");
+    return -EFAULT;
+  }
+
+  err = U_ZERO_ERROR;
+  country_len = uloc_getCountry(uloc_getDefault(),
+      country, ULOC_COUNTRY_CAPACITY, &err);
+  if (!U_SUCCESS(err) || country_len <= 0) {
+    LOGE("Failed to get locale: %s, %s, %d (%s)", u_errorName(err),
+        iso3lang_.c_str(), country_len, country);
+    return -EFAULT;
+  }
+
+  country_ = country;
+
+  return 0;
+}
+
+std::string WidgetServiceManager::GetLangPath() {
+  if (UpdateLangInfo() != 0)
+    return "";
+
+  return iso3lang_ + "-" + country_ + "/";
+}
+
+int WidgetServiceManager::CheckPrivilege(std::string privilege) {
+  int fd = 0;
+  int ret = 0;
+  cynara* p_cynara = nullptr;
+
+  char subject_label[SMACK_LABEL_LEN + 1] = "";
+  char uid[10] = {0,};
+  std::string client_session = "";
+
+  ret = cynara_initialize(&p_cynara, nullptr);
+  if (ret != CYNARA_API_SUCCESS) {
+    LOGE("cannot init cynara [%d] failed!", ret);
+    return -1;
+  }
+
+  fd = open("/proc/self/attr/current", O_RDONLY);
+  if (fd < 0) {
+    LOGE("open [%d] failed!", errno);
+    cynara_finish(p_cynara);
+    return -1;
+  }
+
+  ret = read(fd, subject_label, SMACK_LABEL_LEN);
+  if (ret < 0) {
+    LOGE("read [%d] failed!", errno);
+    close(fd);
+    cynara_finish(p_cynara);
+    return -1;
+  }
+  close(fd);
+
+  snprintf(uid, 10, "%d", getuid());
+
+  ret = cynara_check(p_cynara, subject_label, client_session.c_str(), uid,
+        privilege.c_str());
+  if (ret != CYNARA_API_ACCESS_ALLOWED) {
+    LOGE("cynara access check [%d] failed!", ret);
+    cynara_finish(p_cynara);
+    return -1;
+  }
+
+  cynara_finish(p_cynara);
+
+  return 0;
+}
+
+bool WidgetServiceManager::GetFeatureEnabled() {
+  return feature_enabled_;
+}
+
+void WidgetServiceManager::SetFeatureEnabled() {
+  bool feature = false;
+  int ret;
+
+  ret = system_info_get_platform_bool(
+      "http://tizen.org/feature/shell.appwidget", &feature);
+  if (ret != SYSTEM_INFO_ERROR_NONE) {
+    LOGE("failed to get system info");
+    return;
+  }
+
+  feature_enabled_ = feature;
+}
+
+int WidgetServiceManager::Init() {
+  plugin_.reset(plugin::WidgetServicePlugin::Load());
+  if (!plugin_)
+    return -1;
+
+  if (SetResolutionFromFile() != WIDGET_ERROR_NONE)
+    return -1;
+
+  SetFeatureEnabled();
+
+  is_initialized_ = true;
+
+  return WIDGET_ERROR_NONE;
+}
+
+} // namespace widget_service
diff --git a/src/widget_service_manager.hh b/src/widget_service_manager.hh
new file mode 100644 (file)
index 0000000..449f4ff
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 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 WIDGET_SERVICE_MANAGER_HH
+#define WIDGET_SERVICE_MANAGER_HH
+
+#include <string>
+#include <map>
+#include <memory>
+
+#include "widget_service_plugin_private.hh"
+
+namespace widget_service {
+
+class WidgetServiceManager {
+ public:
+  static WidgetServiceManager& GetInst();
+  std::string GetLangPath();
+  bool GetFeatureEnabled();
+  int CheckPrivilege(std::string privilege);
+  std::string GetType(int width, int height);
+  std::tuple<int, int> GetSize(std::string size_type);
+
+ private:
+  WidgetServiceManager();
+  ~WidgetServiceManager();
+  int Init();
+  std::string GetResolutionFilePath();
+  int SetResolutionFromFile();
+  int UpdateLangInfo();
+  void SetFeatureEnabled();
+
+  bool is_initialized_ = false;
+  std::unique_ptr<plugin::WidgetServicePlugin> plugin_;
+  std::map<std::string, std::pair<int, int>> support_size_map_;
+  std::string syslang_;
+  std::string country_;
+  std::string iso3lang_;
+  bool feature_enabled_ = false;
+};
+
+}  // namespace widget_service
+
+#endif  // WIDGET_SERVICE_MANAGER_HH
diff --git a/src/widget_service_plugin_private.cc b/src/widget_service_plugin_private.cc
new file mode 100644 (file)
index 0000000..87dd1ed
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 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 "widget_service_plugin_private.hh"
+
+#include <dlfcn.h>
+#include <unistd.h>
+
+#include <dlog.h>
+
+#include "debug.h"
+
+namespace {
+
+constexpr const char kPathWidgetServicePlugin[] =
+    "/usr/share/widget_service/plugin/widget_service_plugin.so";
+constexpr const char kGetScreenResolution[] =
+    "WIDGET_SERVICE_GET_SCREEN_RESOLUTION";
+
+}  // namespace
+
+namespace widget_service::plugin {
+
+WidgetServicePlugin::WidgetServicePlugin(void* handle,
+    PluginGetResolutionFunc get_resolution_func)
+    : handle_(handle), get_resolution_func_(get_resolution_func) {
+}
+
+WidgetServicePlugin::~WidgetServicePlugin() {
+  if (handle_)
+    dlclose(handle_);
+}
+
+WidgetServicePlugin* WidgetServicePlugin::Load() {
+  if (access(kPathWidgetServicePlugin, F_OK) != 0) {
+    LOGE("Failed to access (%s)", kPathWidgetServicePlugin);
+    return nullptr;
+  }
+
+  void* handle = dlopen(kPathWidgetServicePlugin, RTLD_LAZY);
+  if (handle == nullptr) {
+    LOGE("dlopen() is failed. path(%s)", kPathWidgetServicePlugin);
+    return nullptr;
+  }
+
+  auto get_resolution_func = reinterpret_cast<PluginGetResolutionFunc>(
+      dlsym(handle, kGetScreenResolution));
+  if (get_resolution_func == nullptr)
+    LOGE("dlsym() is failed. symbol(%s)", kGetScreenResolution);
+
+  return new (std::nothrow) WidgetServicePlugin(handle, get_resolution_func);
+}
+
+std::tuple<int,int> WidgetServicePlugin::GetScreenResolution() {
+  int width = 0;
+  int height = 0;
+
+  if (get_resolution_func_)
+    get_resolution_func_(&width, &height);
+
+  return std::tuple<int, int>(width, height);
+}
+
+}  // namespace widget_service::plugin
diff --git a/src/widget_service_plugin_private.hh b/src/widget_service_plugin_private.hh
new file mode 100644 (file)
index 0000000..6b14aac
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 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 WIDGET_SERVICE_PLUGIN_PRIVATE_HH
+#define WIDGET_SERVICE_PLUGIN_PRIVATE_HH
+
+#include <tuple>
+
+namespace widget_service::plugin {
+
+class WidgetServicePlugin {
+ public:
+  using PluginGetResolutionFunc =
+      int (*)(int* , int*);
+
+  WidgetServicePlugin(void* handle,
+        PluginGetResolutionFunc get_resolution_func);
+  ~WidgetServicePlugin();
+
+  static WidgetServicePlugin* Load();
+  std::tuple<int,int> GetScreenResolution();
+
+ private:
+  void* handle_ = nullptr;
+  PluginGetResolutionFunc get_resolution_func_ = nullptr;
+};
+
+}  // namespace widget_service
+
+#endif  // WIDGET_SERVICE_PLUGIN_PRIVATE_HH
index 3d2ad97416a227a74c94582b1ddb014cce8e0624..9ab2812c3e19b1a25dd8f7731aa5a303be68bd5d 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <widget_service.h>
+#include <widget_service_internal.h>
 #include <string.h>
 #include <aul.h>
 
@@ -66,6 +67,88 @@ int get_content(int argc, char **argv)
        return 0;
 }
 
+bool _widget_service_supported_size_info_cb(widget_supported_size_info_h handle, void *user_data)
+{
+       const char *preview_path;
+       const char *type;
+       int width;
+       int height;
+
+       widget_service_supported_size_info_get_preview_path(handle, &preview_path);
+
+       widget_service_supported_size_info_get_type(handle, &type);
+
+       widget_service_supported_size_info_get_size(handle, &width, &height);
+
+       printf("width:%d\n", width);
+       printf("height:%d\n", height);
+       printf("supported_type:%s\n", type);
+       printf("preview_path:%s\n", preview_path);
+
+       return true;
+}
+
+
+int foreach_supported_sizes(int argc, char **argv)
+{
+       int ret;
+       char *widget_id = argv[2];
+
+       ret = widget_service_foreach_supported_sizes(widget_id,
+               _widget_service_supported_size_info_cb, NULL);
+
+       printf("foreach ret:%d\n", ret);
+
+       return 0;
+}
+
+int get_size_type_from_size(int argc, char **argv)
+{
+       int ret;
+       char *type = NULL;
+       int w = atoi(argv[2]);
+       int h = atoi(argv[3]);
+
+       ret = widget_service_get_size_type_from_size(w, h, &type);
+
+       printf("ret:%d, %s\n", ret, type);
+
+       if (type)
+               free(type);
+
+       return 0;
+}
+
+int get_size_from_size_type(int argc, char **argv)
+{
+       int ret;
+       char *type = argv[2];
+       int width;
+       int height;
+
+       ret = widget_service_get_size_from_size_type(type, &width, &height);
+
+       printf("ret:%d, width : %d, height : %d\n", ret, width, height);
+
+       return 0;
+}
+
+int get_preview_path_from_widget_id(int argc, char **argv)
+{
+       char *path = NULL;
+       char *widget_id = argv[2];
+       char *type = argv[3];
+
+       path = widget_service_get_preview_path_from_widget_id(widget_id, type);
+
+       printf("path : %s\n", path);
+
+       if (path)
+               free(path);
+
+       return 0;
+}
+
 int instance_list_cb(const char *widget_id, const char *instance_id, void *data)
 {
        static int index = 1;
@@ -98,6 +181,10 @@ test_func_t test_func[] = {
        {"get_widget_list", get_widget_list, ""},
        {"get_content", get_content, ""},
        {"get_instance_list", get_instance_list, ""},
+       {"get_size_type_from_size", get_size_type_from_size, "<width>, <height>"},
+       {"get_size_from_size_type", get_size_from_size_type, "<type>"},
+       {"foreach_supported_sizes", foreach_supported_sizes, "<widget_id>"},
+       {"get_preview_path_from_widget_id", get_preview_path_from_widget_id, "<widget_id>, <type>"},
 };
 
 static void print_usage(char *pname)