} 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.
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
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 {
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);
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();
}
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 {
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)) {
}
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 {
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;
}
int target_uid_initialized;
uid_t target_uid;
-int root_path_initialized;
+std::string _initialized_pkgid;
std::string root_path;
uid_t GetTargetUid() {
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);
root_path = path ? path : "./";
pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
- root_path_initialized = 1;
+ _initialized_pkgid = pkgid;
return root_path;
}
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;
#!/bin/sh
#------------------------------------------#
-# widget service patch for upgrade (4.0 -> 5.x) #
+# widget service patch for upgrade #
#------------------------------------------#
# Macro
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
chmod 666 $DB_ETC_WIDGET_SERVICE
chmod 666 $DB_ETC_WIDGET_SERVICE-journal
+}
+
+UpdateWidgetDB() {
+
+echo "## update widget db"
+
+UpdateDB
+UpdatePermission
+
+}
+
+UpdateWidgetDB
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)
${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
CYNARA_CLIENT_DEPS
INIPARSER_DEPS
SMACK_DEPS
+ DATABASE_DEPS
)
INSTALL(TARGETS ${TARGET_WIDGET_SERVICE} DESTINATION ${LIB_INSTALL_DIR})
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)
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 ( \
syslang = vconf_get_str(VCONFKEY_LANGSET);
if (!syslang) {
- ErrPrint("Failed to get vconf-lang");
+ _E("Failed to get vconf-lang");
return -EFAULT;
}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
#include <stdio.h>
#include <stdlib.h>
#include <widget_service.h>
+#include <widget_service_internal.h>
#include <string.h>
#include <aul.h>
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;
{"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)