From: jusung son Date: Fri, 13 Apr 2018 04:26:06 +0000 (+0900) Subject: Add validation check logic to the provider side X-Git-Tag: accepted/tizen/unified/20180503.080745~16 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7eed933e556287316720204645505eb73febabe;p=platform%2Fcore%2Fappfw%2Fwatchface-complication.git Add validation check logic to the provider side Related chage: - https://review.tizen.org/gerrit/#/c/175865/ Change-Id: Ib2ee58c0515e6abe34cfdfc9fae6a64869f446c3 Signed-off-by: jusung son --- diff --git a/packaging/libwatchface-complication.spec b/packaging/libwatchface-complication.spec index 9a7fabd..582e3c6 100644 --- a/packaging/libwatchface-complication.spec +++ b/packaging/libwatchface-complication.spec @@ -24,6 +24,8 @@ BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(pkgmgr-installer) BuildRequires: pkgconfig(capi-appfw-app-control) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-creds-gdbus) %if 0%{?gcov:1} BuildRequires: lcov %endif diff --git a/unittest/src/test_complication_provider.cc b/unittest/src/test_complication_provider.cc index 74caaf4..ace3d3e 100644 --- a/unittest/src/test_complication_provider.cc +++ b/unittest/src/test_complication_provider.cc @@ -35,7 +35,7 @@ class WCP : public ::testing::Test { ComplicationProvider* provider; virtual void SetUp(){ - provider = new ComplicationProvider(providerId.c_str(), 1); + provider = new ComplicationProvider(providerId.c_str()); } virtual void TearDown(){ delete provider; diff --git a/watchface-common/watchface-util.cc b/watchface-common/watchface-util.cc new file mode 100644 index 0000000..33da075 --- /dev/null +++ b/watchface-common/watchface-util.cc @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2018 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "watchface-util.h" +#include "watchface-complication/include/watchface-common.h" + + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define MAX_PACKAGE_STR_SIZE 512 +#define SMACK_LABEL_LEN 255 + +#define LOG_TAG "WATCHFACE_COMPLICATION" + +namespace watchface_complication { + namespace util { + static int __cynara_check(const char* client, const char* user, const char* privilege) { + int ret, cynara_ret; + cynara* p_cynara = NULL; + + ret = cynara_initialize(&p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + LOGE("cannot init cynara [%d] failed!", ret); + return COMPLICATION_ERROR_IO_ERROR; + } + + cynara_ret = cynara_check(p_cynara, client, "", user, privilege); + if (cynara_ret == CYNARA_API_ACCESS_ALLOWED) { + ret = COMPLICATION_ERROR_NONE; + } else { + if (cynara_ret == CYNARA_API_ACCESS_DENIED) + ret = COMPLICATION_ERROR_PERMISSION_DENIED; + else + ret = COMPLICATION_ERROR_IO_ERROR; + + LOGE("cynara access check [%s][%d] failed!", privilege, ret); + } + + cynara_finish(p_cynara); + + return ret; + } + + int CheckPrivilege(const char* privilege) { + int fd; + int ret; + char subject_label[SMACK_LABEL_LEN + 1] = ""; + char uid[10] = {0,}; + + fd = open("/proc/self/attr/current", O_RDONLY); + if (fd == -1) { + LOGE("open [%d] failed!", errno); + return COMPLICATION_ERROR_IO_ERROR; + } + + ret = read(fd, subject_label, SMACK_LABEL_LEN); + if (ret < 0) { + LOGE("read [%d] failed!", errno); + ret = COMPLICATION_ERROR_IO_ERROR; + } else { + snprintf(uid, 10, "%d", getuid()); + ret = __cynara_check(subject_label, uid, privilege); + } + + close(fd); + return ret; + } + + int CheckPrivilege(std::string& privilege, GDBusConnection* connection, + std::string& sender_name, std::string& sender_appid) { + int ret; + char *client = NULL; + char *user = NULL; + + ret = cynara_creds_gdbus_get_client(connection, sender_name.c_str(), + CLIENT_METHOD_DEFAULT, &client); + if (ret != CYNARA_API_SUCCESS) { + LOGE("failed to get client"); + ret = COMPLICATION_ERROR_IO_ERROR; + goto out; + } + + ret = cynara_creds_gdbus_get_user(connection, sender_name.c_str(), + USER_METHOD_DEFAULT, &user); + if (ret != CYNARA_API_SUCCESS) { + LOGE("failed to get user"); + ret = COMPLICATION_ERROR_IO_ERROR; + goto out; + } + + LOGD("app_id(%s), client(%s), user(%s)", sender_appid.c_str(), client, user); + + ret = __cynara_check(client, user, privilege.c_str()); + +out: + if (client) + free(client); + if (user) + free(user); + + return ret; + } + + int GetSenderPid(GDBusConnection *conn, const std::string& sender_name) { + GDBusMessage *msg = NULL; + GDBusMessage *reply = NULL; + GError *err = NULL; + GVariant *body; + int pid = 0; + + msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", + "org.freedesktop.DBus", "GetConnectionUnixProcessID"); + if (!msg) { + LOGE("Can't allocate new method call"); + goto out; + } + + g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name.c_str())); + reply = g_dbus_connection_send_message_with_reply_sync(conn, msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err); + + if (!reply) { + if (err != NULL) { + LOGE("Failed to get pid [%s]", err->message); + g_error_free(err); + } + goto out; + } + + body = g_dbus_message_get_body(reply); + g_variant_get(body, "(u)", &pid); + +out: + if (msg) + g_object_unref(msg); + if (reply) + g_object_unref(reply); + + return pid; + } + + bool CheckSender(const char* sender_app_id, + const std::string& sender_name, + GDBusConnection* conn, + int* sender_pid) { + int ret = 0; + char buffer[MAX_PACKAGE_STR_SIZE] = {0, }; + int pid = GetSenderPid(conn, sender_name); + + ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer)); + if (ret != AUL_R_OK) { + LOGE("Failed to get the sender ID: (%s) (%d)", sender_name.c_str(), pid); + return false; + } + + if (strcmp(buffer, sender_app_id) != 0) { + LOGE("invalid appid : (%s) (%s)", buffer, sender_app_id); + return false; + } + *sender_pid = pid; + + return true; + } + } /* namespace util */ +} /* namespace watchface_complication */ diff --git a/watchface-common/watchface-util.h b/watchface-common/watchface-util.h new file mode 100644 index 0000000..db9ee0e --- /dev/null +++ b/watchface-common/watchface-util.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 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 WATCHFACE_COMPLICATION_UTIL_H_ +#define WATCHFACE_COMPLICATION_UTIL_H_ + +#include +#include +#include "watchface-complication/include/watchface-common.h" +namespace watchface_complication { + namespace util { + int CheckPrivilege(const char* privilege); + int CheckPrivilege(std::string& privilege, + GDBusConnection *connection, + std::string& sender_name, + std::string& sender_appid); + int GetSenderPid(GDBusConnection *conn, const std::string& sender_name); + bool CheckSender(const char* sender_app_id, + const std::string& sender_name, + GDBusConnection* conn, + int* sender_pid); + } +} /* namespace watchface_complication */ + +#endif /* WATCHFACE_COMPLICATION_DB_MANAGER_H_ */ \ No newline at end of file diff --git a/watchface-complication-provider/CMakeLists.txt b/watchface-complication-provider/CMakeLists.txt index 61ab633..c0decd6 100644 --- a/watchface-complication-provider/CMakeLists.txt +++ b/watchface-complication-provider/CMakeLists.txt @@ -15,6 +15,8 @@ pkg_check_modules(watchface-complication-provider REQUIRED dlog aul capi-appfw-app-control + cynara-client + cynara-creds-gdbus ) FOREACH(flag ${watchface-complication-provider_CFLAGS}) @@ -26,10 +28,12 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../watchface-common) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../watchface-common SOURCES) ADD_LIBRARY (${PROJECT_NAME} SHARED ${SOURCES}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) diff --git a/watchface-complication-provider/complication-provider-implementation.h b/watchface-complication-provider/complication-provider-implementation.h index e002a9a..d3a31f1 100644 --- a/watchface-complication-provider/complication-provider-implementation.h +++ b/watchface-complication-provider/complication-provider-implementation.h @@ -22,10 +22,17 @@ #include #include #include +#include #include "watchface-complication/complication.h" #include "watchface-complication/complication-connector.h" +enum provider_cynara_result { + COMPLICATION_CYNARA_UNKNOWN, + COMPLICATION_CYNARA_ALLOWED, + COMPLICATION_CYNARA_DENIED, +}; + namespace watchface_complication { class ComplicationProvider::Impl : ComplicationConnector::IEventListener { @@ -35,15 +42,35 @@ class ComplicationProvider::Impl : ComplicationConnector::IEventListener { private: friend class ComplicationProvider; - void OnSignal(const std::string& sender_name, + void OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, GVariant* parameters) override; void OnVanish(const std::string& name) override; void OnAppear(const std::string& name, const std::string& name_owner) override; - Impl(ComplicationProvider* parent, const std::string& provider_id, - int support_types); + std::list& GetRequiredPrivileges(); + Impl(ComplicationProvider* parent, const std::string& provider_id); + class SenderInfo { + public: + SenderInfo(const std::string& sender_name, const char* sender_app_id, + int watcher_id, int pid); + int CheckPrivilege(std::list& required_privileges, GDBusConnection* connection); + bool CheckAppid(const std::string& Appid); + int GetWatcherID(); + int GetPID(); + provider_cynara_result GetPrivilegeResult(); + void SetPrivilegeResult(provider_cynara_result result); + + private: + std::string sender_name_; + std::string sender_app_id_; + int watcher_id_; + int pid_; + std::list sender_privileges_; + provider_cynara_result privilege_result_; + }; private: ComplicationProvider* parent_; @@ -51,6 +78,8 @@ class ComplicationProvider::Impl : ComplicationConnector::IEventListener { std::string provider_id_; std::string setup_appid_; int support_types_; + std::map sender_info_; + std::list required_privileges_; }; } // namespace watchface_complication diff --git a/watchface-complication-provider/complication-provider.cc b/watchface-complication-provider/complication-provider.cc index b01f036..1d125da 100644 --- a/watchface-complication-provider/complication-provider.cc +++ b/watchface-complication-provider/complication-provider.cc @@ -17,33 +17,115 @@ #include #include -#include "watchface-complication-provider/complication-provider.h" -#include "watchface-complication-provider/complication-provider-implementation.h" +#include "watchface-util.h" +#include "complication-provider.h" +#include "complication-provider-implementation.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "WATCHFACE_COMPLICATION" +#define PRIVILEGE_DATASHARING "http://tizen.org/privilege/datasharing" namespace watchface_complication { -ComplicationProvider::ComplicationProvider(const std::string& provider_id, - int support_types) : impl_(new Impl(this, provider_id, support_types)) { +ComplicationProvider::ComplicationProvider(const std::string& provider_id) + : impl_(new Impl(this, provider_id)) { } ComplicationProvider::~ComplicationProvider() = default; + ComplicationProvider::Impl::Impl(ComplicationProvider* parent, - const std::string& provider_id, - int support_types) - : parent_(parent), provider_id_(provider_id), support_types_(support_types) { + const std::string& provider_id) + : parent_(parent), provider_id_(provider_id) { subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal( ComplicationConnector::Complication, provider_id_, -1, this); + + std::list privlege_list; + required_privileges_.push_back(std::string(PRIVILEGE_DATASHARING)); + + DBManager::GetSupportTypes(provider_id_, &support_types_); + + privlege_list = DBManager::GetRequiredPrivlegeList(provider_id_); + for (auto& i : privlege_list) { + required_privileges_.push_back(i); + LOGI("required_privileges %s", i.c_str()); + } + LOGI("subscribe signal %d", subscribe_id_); } +ComplicationProvider::Impl::SenderInfo::SenderInfo(const std::string& sender_name, + const char* sender_app_id, + int watcher_id, + int pid) + : sender_name_(sender_name), sender_app_id_(sender_app_id), + watcher_id_(watcher_id), pid_(pid), privilege_result_(COMPLICATION_CYNARA_UNKNOWN) { +} + +int ComplicationProvider::Impl::SenderInfo::CheckPrivilege(std::list& required_privileges, + GDBusConnection* connection) { + bool ret; + int privilege_result; + + for (auto& i : required_privileges) { + ret = false; + for (auto& j : sender_privileges_) { + if (i.compare(j) == 0) { + ret = true; + break; + } + } + + if (ret == false) { + privilege_result = watchface_complication::util::CheckPrivilege(i, + connection, sender_name_, sender_app_id_); + if (privilege_result == COMPLICATION_ERROR_NONE) + sender_privileges_.push_back(i); + else + return privilege_result; + } + } + return COMPLICATION_ERROR_NONE; +} + +bool ComplicationProvider::Impl::SenderInfo::CheckAppid(const std::string& Appid) { + if (sender_app_id_.compare(Appid) == 0) + return true; + return false; + } + +int ComplicationProvider::Impl::SenderInfo::GetWatcherID() { + return watcher_id_; +} + +int ComplicationProvider::Impl::SenderInfo::GetPID() { + return pid_; +} + +provider_cynara_result ComplicationProvider::Impl::SenderInfo::GetPrivilegeResult() { + return privilege_result_; +} + +void ComplicationProvider::Impl::SenderInfo::SetPrivilegeResult(provider_cynara_result result) { + privilege_result_ = result; +} + +std::list& ComplicationProvider::Impl::GetRequiredPrivileges() { + return required_privileges_; +} + void ComplicationProvider::Impl::OnVanish(const std::string& name) { + auto sender_info = sender_info_.find(name); + auto si = sender_info->second; + if (sender_info == sender_info_.end()) + return; + + ComplicationConnector::GetInst().UnWatch(si->GetWatcherID()); + sender_info_.erase(name); + delete si; } void ComplicationProvider::Impl::OnAppear(const std::string& name, @@ -51,7 +133,8 @@ void ComplicationProvider::Impl::OnAppear(const std::string& name, } -void ComplicationProvider::Impl::OnSignal(const std::string& sender_name, +void ComplicationProvider::Impl::OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, @@ -61,20 +144,77 @@ void ComplicationProvider::Impl::OnSignal(const std::string& sender_name, int complication_id; char *context_raw = NULL; int type; - Bundle* shared_data = new Bundle(); - LOGI("signal_name: %s", signal_name.c_str()); + auto sender_info = sender_info_.find(sender_name); + auto si = sender_info->second; + + if (sender_info == sender_info_.end()) { + char* sender_app_id = NULL; + int watcher_id; + int pid; + g_variant_get_child(parameters, 0, "&s", &sender_app_id); + + if (sender_app_id == NULL || + !util::CheckSender(sender_app_id, sender_name, connection, &pid)) { + LOGE("sender_app_id %s", sender_app_id); + return; + } + + watcher_id = ComplicationConnector::GetInst().Watch( + std::string(sender_app_id), this); + + si = new SenderInfo(sender_name, sender_app_id, watcher_id, pid); + sender_info_[sender_name] = si; + LOGI("create new sender_info_ "); + } + + if (si->GetPrivilegeResult() == COMPLICATION_CYNARA_DENIED) { + /* For performance, the senderInfo does not delete + Probably the sender will connect again + When the sender is terminated, It is deleted on OnVanish */ + LOGE("Permission denied"); + return; + } + + if (si->GetPrivilegeResult() == COMPLICATION_CYNARA_UNKNOWN) { + int ret = si->CheckPrivilege(GetRequiredPrivileges(), connection); + + if (ret != COMPLICATION_ERROR_NONE) { + if (ret == COMPLICATION_ERROR_PERMISSION_DENIED) + si->SetPrivilegeResult(COMPLICATION_CYNARA_DENIED); + + LOGE("Permission denied [%d]", ret); + return; + } + + si->SetPrivilegeResult(COMPLICATION_CYNARA_ALLOWED); + } + if (signal_name.compare( ComplicationConnector::GetInst().GetCmdStr( ComplicationConnector::CompUpdateRequest)) == 0) { g_variant_get(parameters, "(&sii&s)", &sender_app_id, &complication_id, &type, &context_raw); + + if (si->CheckAppid(sender_app_id) == false) { + LOGE("invaild app id [%s]", sender_app_id); + return; + } + + if ((support_types_ & type) == 0) { + LOGE("Not supported type [%d][%d]", support_types_, type); + return; + } + LOGI("get : %s, %d, %d", sender_app_id, complication_id, type); + Bundle* context_data = new Bundle(std::string(context_raw)); + Bundle* shared_data = new Bundle(); /* Call update request callback and fill shared data */ parent_->OnDataUpdateRequest(sender_app_id, (ComplicationType)type, context_data, shared_data); + delete context_data; ComplicationConnector::GetInst().EmitSignal( ComplicationConnector::Complication, std::string(sender_app_id), @@ -86,6 +226,7 @@ void ComplicationProvider::Impl::OnSignal(const std::string& sender_name, type, complication_id, shared_data->ToString())); + delete shared_data; } } @@ -97,15 +238,42 @@ const std::string& ComplicationProvider::GetProviderId() const { return impl_->provider_id_; } -void ComplicationProvider::NotifyDataUpdate() { - LOGI("notify %s", impl_->provider_id_.c_str()); - ComplicationConnector::GetInst().EmitSignal( - ComplicationConnector::Complication, - "", - impl_->provider_id_, -1, - ComplicationConnector::GetInst().GetCmdStr( - ComplicationConnector::CompNotifyDataUpdate), - NULL); +int ComplicationProvider::NotifyDataUpdate() { + LOGI("notify %s", impl_->provider_id_.c_str()); + + static provider_cynara_result pcr = COMPLICATION_CYNARA_UNKNOWN; + + int ret = COMPLICATION_ERROR_NONE; + bool emit_ret; + + if (pcr == COMPLICATION_CYNARA_DENIED) { + LOGE("Permission denied"); + return COMPLICATION_ERROR_PERMISSION_DENIED; + + } else if (pcr == COMPLICATION_CYNARA_UNKNOWN) { + ret = util::CheckPrivilege(PRIVILEGE_DATASHARING); + if (ret == COMPLICATION_ERROR_NONE) { + pcr = COMPLICATION_CYNARA_ALLOWED; + } else if (ret == COMPLICATION_ERROR_PERMISSION_DENIED) { + pcr = COMPLICATION_CYNARA_DENIED; + return ret; + } else { + return ret; + } + } + + emit_ret = ComplicationConnector::GetInst().EmitSignal( + ComplicationConnector::Complication, + "", + impl_->provider_id_, -1, + ComplicationConnector::GetInst().GetCmdStr( + ComplicationConnector::CompNotifyDataUpdate), + NULL); + + if (emit_ret == false) + ret = COMPLICATION_ERROR_IO_ERROR; + + return ret; } } // namespace watchface_complication diff --git a/watchface-complication-provider/complication-provider.h b/watchface-complication-provider/complication-provider.h index a7448be..e24b675 100644 --- a/watchface-complication-provider/complication-provider.h +++ b/watchface-complication-provider/complication-provider.h @@ -24,11 +24,13 @@ #include "watchface-complication/complication-event-interface.h" #include "watchface-complication/complication-connector.h" +#define PRIVILEGE_DATASHARING "http://tizen.org/privilege/datasharing" + namespace watchface_complication { class EXPORT_API ComplicationProvider : public IComplicationEvent { public: - ComplicationProvider(const std::string& provider_id, int support_types); + ComplicationProvider(const std::string& provider_id); virtual ~ComplicationProvider(); public: @@ -37,7 +39,7 @@ class EXPORT_API ComplicationProvider : public IComplicationEvent { const Bundle* context, Bundle* shared_data) override; - void NotifyDataUpdate(); + int NotifyDataUpdate(); const std::string& GetProviderId() const; private: diff --git a/watchface-complication-provider/watchface-complication-provider.cc b/watchface-complication-provider/watchface-complication-provider.cc index 567ecd8..7b2b6d2 100644 --- a/watchface-complication-provider/watchface-complication-provider.cc +++ b/watchface-complication-provider/watchface-complication-provider.cc @@ -21,12 +21,17 @@ #include #include #include +#include +#include #include +#include #include #include -#include "watchface-complication-provider/complication-provider.h" -#include "watchface-complication-provider/include/watchface-complication-provider.h" +#include "watchface-util.h" +#include "complication-provider.h" +#include "include/watchface-complication-provider.h" +#include "watchface-complication/db-manager.h" #include "watchface-complication/include/watchface-complication-internal.h" #ifdef LOG_TAG @@ -51,6 +56,10 @@ class CallbackInfo { shared_data->GetRaw(), user_data_); } + on_update_request_cb GetCallback() { + return cb_; + } + private: on_update_request_cb cb_; void* user_data_; @@ -58,10 +67,8 @@ class CallbackInfo { class WatchComplicationProviderStub : public ComplicationProvider { public: - WatchComplicationProviderStub(const std::string& provider_id, - int support_types) - : ComplicationProvider(provider_id, - support_types) { + WatchComplicationProviderStub(const std::string& provider_id) + : ComplicationProvider(provider_id) { } virtual ~WatchComplicationProviderStub() = default; @@ -74,17 +81,25 @@ class WatchComplicationProviderStub : public ComplicationProvider { sender_appid.c_str()); } - void AddCallbackInfo(CallbackInfo* ci) { + int AddCallbackInfo(CallbackInfo* ci) { + for (auto& i : cb_list_) { + if (i.get()->GetCallback() == ci->GetCallback()) { + LOGI("already registered callback"); + return COMPLICATION_ERROR_INVALID_PARAMETER; + } + } cb_list_.emplace_back(ci); + return COMPLICATION_ERROR_NONE; } - void RemoveCallbackInfo(CallbackInfo* ci) { + int RemoveCallbackInfo(on_update_request_cb ci) { for (auto& i : cb_list_) { - if (i.get() == ci) { + if (i.get()->GetCallback() == ci) { cb_list_.remove(i); - break; + return COMPLICATION_ERROR_NONE; } } + return COMPLICATION_ERROR_INVALID_PARAMETER; } private: @@ -98,22 +113,28 @@ extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_add( if (provider_id == NULL || cb == NULL) return COMPLICATION_ERROR_INVALID_PARAMETER; - // TODO(?): Provider ID validation - // TODO(?): Get provider's support type from storage - int support_types = ShortText | Image; + std::string appid = DBManager::GetProviderAppId(provider_id); + if (appid.compare(ComplicationConnector::GetInst().GetAppId()) != 0) { + LOGE("Invalid provider id : %s", provider_id); + return COMPLICATION_ERROR_INVALID_PARAMETER; + } + + int ret = COMPLICATION_ERROR_NONE; auto cp = __providers.find(provider_id); auto ws = cp->second; if (cp == __providers.end()) { - ws = new WatchComplicationProviderStub(provider_id, support_types); + ws = new WatchComplicationProviderStub(provider_id); __providers[provider_id] = ws; LOGI("create new provider : %s", provider_id); } auto ci = new CallbackInfo(cb, user_data); - ws->AddCallbackInfo(ci); + ret = ws->AddCallbackInfo(ci); + if (ret != COMPLICATION_ERROR_NONE) + delete ci; - return 0; + return ret; } extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_del( @@ -121,7 +142,14 @@ extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_del( if (provider_id == NULL || cb == NULL) return COMPLICATION_ERROR_INVALID_PARAMETER; - return 0; + auto cp = __providers.find(provider_id); + auto ws = cp->second; + + if (cp == __providers.end()) { + return COMPLICATION_ERROR_INVALID_PARAMETER; + } + + return ws->RemoveCallbackInfo(cb); } extern "C" EXPORT_API int watchface_complication_provider_get_support_types( @@ -134,6 +162,9 @@ extern "C" EXPORT_API int watchface_complication_provider_get_support_types( extern "C" EXPORT_API int watchface_complication_provider_notify_update( const char *updated_provider_id) { + if (updated_provider_id == NULL) + return COMPLICATION_ERROR_INVALID_PARAMETER; + auto cp = __providers.find(updated_provider_id); if (cp == __providers.end()) { @@ -142,18 +173,8 @@ extern "C" EXPORT_API int watchface_complication_provider_notify_update( } auto ws = cp->second; - // TODO(?): Get provider's support type from storage - int support_types = ShortText | Image; - - if (cp == __providers.end()) { - LOGI("create new provider : %s", updated_provider_id); - ws = new WatchComplicationProviderStub(updated_provider_id, support_types); - __providers[updated_provider_id] = ws; - } - - ws->NotifyDataUpdate(); - return COMPLICATION_ERROR_NONE; + return ws->NotifyDataUpdate(); } extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor( @@ -164,6 +185,7 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor( int ret; int str_len = 0; bundle_raw* raw_data = NULL; + bool emit_signal_ret; ret = app_control_get_extra_data(handle, SETUP_EDITOR_APPID_KEY, &editor_appid); if (ret != 0) { @@ -173,6 +195,8 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor( ret = app_control_get_extra_data(handle, SETUP_EDITABLE_ID_KEY, &editable_id); if (ret != APP_CONTROL_ERROR_NONE) { + free(editor_appid); + if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) { LOGE("Fail to get context data"); return COMPLICATION_ERROR_OUT_OF_MEMORY; @@ -191,7 +215,7 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor( } } - ComplicationConnector::GetInst().EmitSignal( + emit_signal_ret = ComplicationConnector::GetInst().EmitSignal( ComplicationConnector::Editable, std::string(editor_appid), std::string(editor_appid), -1, @@ -204,6 +228,9 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor( free(editable_id); free(raw_data); + if (emit_signal_ret == false) + return COMPLICATION_ERROR_IO_ERROR; + return COMPLICATION_ERROR_NONE; } @@ -530,23 +557,32 @@ extern "C" EXPORT_API int watchface_complication_provider_is_touch_launch( app_control_h handle, bool* is_touch_launch) { int ret; char* value = NULL; + bundle *data; if (handle == NULL || is_touch_launch == NULL) { LOGE("Invalid param"); return COMPLICATION_ERROR_INVALID_PARAMETER; } - ret = app_control_get_extra_data(handle, TOUCH_LAUNCH_DATA_KEY, &value); - free(value); - if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) { - LOGE("Out of memory"); - return COMPLICATION_ERROR_OUT_OF_MEMORY; - } else if (ret == APP_CONTROL_ERROR_NONE) { - *is_touch_launch = true; - } else { + ret = app_control_to_bundle(handle, &data); + if (ret != APP_CONTROL_ERROR_NONE) { + LOGE("Invalid param"); + return COMPLICATION_ERROR_INVALID_PARAMETER; + } + + ret = bundle_get_str(data, AUL_K_COMPLICATION_MODE, &value); + if (ret != BUNDLE_ERROR_NONE) { *is_touch_launch = false; - return COMPLICATION_ERROR_IO_ERROR; + return COMPLICATION_ERROR_NONE; } + + ret = bundle_get_str(data, TOUCH_LAUNCH_DATA_KEY, &value); + if (ret != BUNDLE_ERROR_NONE) { + *is_touch_launch = false; + return COMPLICATION_ERROR_NONE; + } + + *is_touch_launch = true; return COMPLICATION_ERROR_NONE; } diff --git a/watchface-complication/complication-connector-implementation.h b/watchface-complication/complication-connector-implementation.h index c2980a7..25c501c 100644 --- a/watchface-complication/complication-connector-implementation.h +++ b/watchface-complication/complication-connector-implementation.h @@ -45,7 +45,7 @@ class ComplicationConnector::Impl { void* user_data) { IEventListener* rs = static_cast(user_data); - rs->OnSignal(sender_name, object_path, interface_name, + rs->OnSignal(connection, sender_name, object_path, interface_name, signal_name, parameters); } diff --git a/watchface-complication/complication-connector.h b/watchface-complication/complication-connector.h index d6ad162..587d74d 100644 --- a/watchface-complication/complication-connector.h +++ b/watchface-complication/complication-connector.h @@ -46,7 +46,8 @@ class EXPORT_API ComplicationConnector { class IEventListener { public: - virtual void OnSignal(const std::string& sender_name, + virtual void OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, diff --git a/watchface-complication/complication-implementation.h b/watchface-complication/complication-implementation.h index 56479e5..742ce0d 100644 --- a/watchface-complication/complication-implementation.h +++ b/watchface-complication/complication-implementation.h @@ -37,7 +37,8 @@ namespace watchface_complication { class Complication::Impl : ComplicationConnector::IEventListener { public: - void OnSignal(const std::string& sender_name, + void OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, diff --git a/watchface-complication/complication.cc b/watchface-complication/complication.cc index 07a8c9d..d5cce6c 100644 --- a/watchface-complication/complication.cc +++ b/watchface-complication/complication.cc @@ -90,7 +90,8 @@ void Complication::Impl::OnAppear(const std::string& name, } -void Complication::Impl::OnSignal(const std::string& sender_name, +void Complication::Impl::OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, @@ -227,7 +228,7 @@ int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id, } std::string Complication::Impl::GetProviderAppId() { - return DBManager::GetProviderAppId(cur_provider_id_); + return DBManager::GetProviderAppId(cur_provider_id_.c_str()); } int Complication::GetComplicationId() { diff --git a/watchface-complication/db-manager.cc b/watchface-complication/db-manager.cc index 10db708..75410fb 100644 --- a/watchface-complication/db-manager.cc +++ b/watchface-complication/db-manager.cc @@ -69,7 +69,7 @@ std::unique_ptr DBManager::GetDefaultData(const char* provider_id, std::unique_ptr default_data = nullptr; const char* raw_data; sqlite3_stmt* stmt; - sqlite3* db = NULL; + sqlite3* db; int ret; static const char query[] = @@ -98,19 +98,17 @@ std::unique_ptr DBManager::GetDefaultData(const char* provider_id, default_data = std::unique_ptr(new Bundle(std::string(raw_data))); } - if (stmt) - sqlite3_finalize(stmt); - + sqlite3_finalize(stmt); CloseDB(db); return std::move(default_data); } -std::string DBManager::GetProviderAppId(std::string& provider_id) { +std::string DBManager::GetProviderAppId(const char* provider_id) { int ret; std::string appid; sqlite3_stmt *stmt = NULL; - sqlite3* db = NULL; + sqlite3* db; static const char query[] = "SELECT DISTINCT appid FROM complication_provider " @@ -130,15 +128,13 @@ std::string DBManager::GetProviderAppId(std::string& provider_id) { return NULL; } - sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 1, provider_id, -1, SQLITE_TRANSIENT); if (sqlite3_step(stmt) == SQLITE_ROW) { appid = std::string((char *)sqlite3_column_text(stmt, 0)); } - if (stmt) - sqlite3_finalize(stmt); - + sqlite3_finalize(stmt); CloseDB(db); return appid; @@ -148,7 +144,7 @@ std::list DBManager::GetProviderList(int support_type) { int ret; char *provider_id = NULL; sqlite3_stmt* stmt; - sqlite3* db = NULL; + sqlite3* db; std::list provider_list; static const char query[] = @@ -176,14 +172,87 @@ std::list DBManager::GetProviderList(int support_type) { provider_list.push_back(std::string(provider_id)); } - if (stmt) - sqlite3_finalize(stmt); - + sqlite3_finalize(stmt); CloseDB(db); return provider_list; } +int DBManager::GetSupportTypes(std::string& provider_id, int* types) { + int ret; + int support_types = 0; + sqlite3_stmt* stmt; + sqlite3* db; + + static const char query[] = + "SELECT SUM(support_type) FROM complication_provider " + "WHERE provider_id = ?"; + + db = OpenDB(); + if (db == NULL) { + LOGE("parser db not exist"); + return COMPLICATION_ERROR_DB; + } + + ret = sqlite3_prepare_v2(db, query, strlen(query), + &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("prepare error: %s", sqlite3_errmsg(db)); + CloseDB(db); + return COMPLICATION_ERROR_DB; + } + + sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT); + + while (sqlite3_step(stmt) == SQLITE_ROW) + support_types = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + CloseDB(db); + + *types = support_types; + + return COMPLICATION_ERROR_NONE; +} + +std::list DBManager::GetRequiredPrivlegeList(std::string& provider_id) { + int ret; + char *privlege = NULL; + sqlite3_stmt* stmt; + sqlite3* db; + std::list privlege_list; + + static const char query[] = + "SELECT DISTINCT privilege FROM provider_privilege " + "WHERE provider_id=?"; + + db = OpenDB(); + if (db == NULL) { + LOGE("parser db not exist"); + return privlege_list; + } + + ret = sqlite3_prepare_v2(db, query, strlen(query), + &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("prepare error: %s", sqlite3_errmsg(db)); + CloseDB(db); + return privlege_list; + } + + sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT); + + while (sqlite3_step(stmt) == SQLITE_ROW) { + privlege = (char *)sqlite3_column_text(stmt, 0); + privlege_list.push_back(std::string(privlege)); + } + + sqlite3_finalize(stmt); + CloseDB(db); + + return privlege_list; +} + const char* DBManager::GetParserDataPath() { uid_t target_uid; const char *path; diff --git a/watchface-complication/db-manager.h b/watchface-complication/db-manager.h index 3c4c67e..e636a92 100644 --- a/watchface-complication/db-manager.h +++ b/watchface-complication/db-manager.h @@ -32,8 +32,10 @@ class EXPORT_API DBManager { public: static std::unique_ptr GetDefaultData(const char* provider_id, int support_type); - static std::string GetProviderAppId(std::string& provider_id); + static std::string GetProviderAppId(const char* provider_id); static std::list GetProviderList(int support_type); + static std::list GetRequiredPrivlegeList(std::string& provider_id); + static int GetSupportTypes(std::string& provider_id, int* types); private: DBManager(); diff --git a/watchface-complication/editables-container-implementation.h b/watchface-complication/editables-container-implementation.h index e9c9df8..f1c5b4d 100644 --- a/watchface-complication/editables-container-implementation.h +++ b/watchface-complication/editables-container-implementation.h @@ -35,7 +35,8 @@ class EditablesContainer::Impl : ComplicationConnector::IEventListener { private: friend class EditablesContainer; - void OnSignal(const std::string& sender_name, + void OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, diff --git a/watchface-complication/editables-container.cc b/watchface-complication/editables-container.cc index 762ecd4..be50d21 100644 --- a/watchface-complication/editables-container.cc +++ b/watchface-complication/editables-container.cc @@ -45,7 +45,8 @@ EditablesContainer::Impl::Impl(EditablesContainer* parent) LOGI("subscribe signal %d", subscribe_id_); } -void EditablesContainer::Impl::OnSignal(const std::string& sender_name, +void EditablesContainer::Impl::OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, diff --git a/watchface-editor/editables-editor-implementation.h b/watchface-editor/editables-editor-implementation.h index 20bf6e9..8d6b76f 100644 --- a/watchface-editor/editables-editor-implementation.h +++ b/watchface-editor/editables-editor-implementation.h @@ -35,7 +35,8 @@ class EditablesEditor::Impl : ComplicationConnector::IEventListener { private: friend class EditablesEditor; - void OnSignal(const std::string& sender_name, + void OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name, diff --git a/watchface-editor/editables-editor.cc b/watchface-editor/editables-editor.cc index b6662bf..59fb0cc 100644 --- a/watchface-editor/editables-editor.cc +++ b/watchface-editor/editables-editor.cc @@ -53,7 +53,8 @@ void EditablesEditor::Impl::OnAppear(const std::string& name, } -void EditablesEditor::Impl::OnSignal(const std::string& sender_name, +void EditablesEditor::Impl::OnSignal(GDBusConnection* connection, + const std::string& sender_name, const std::string& object_path, const std::string& interface_name, const std::string& signal_name,