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
ComplicationProvider* provider;
virtual void SetUp(){
- provider = new ComplicationProvider(providerId.c_str(), 1);
+ provider = new ComplicationProvider(providerId.c_str());
}
virtual void TearDown(){
delete provider;
--- /dev/null
+/*
+ * 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 <dlog.h>
+#include <unistd.h>
+#include <aul.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <string>
+#include <cynara-client.h>
+#include <cynara-creds-gdbus.h>
+#include <cynara-session.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <gio/gio.h>
+#include <string>
+#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
dlog
aul
capi-appfw-app-control
+ cynara-client
+ cynara-creds-gdbus
)
FOREACH(flag ${watchface-complication-provider_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})
#include <memory>
#include <string>
#include <list>
+#include <map>
#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 {
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<std::string>& 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<std::string>& 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<std::string> sender_privileges_;
+ provider_cynara_result privilege_result_;
+ };
private:
ComplicationProvider* parent_;
std::string provider_id_;
std::string setup_appid_;
int support_types_;
+ std::map<std::string, SenderInfo*> sender_info_;
+ std::list<std::string> required_privileges_;
};
} // namespace watchface_complication
#include <glib.h>
#include <unistd.h>
-#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<std::string> 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<std::string>& 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<std::string>& 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,
}
-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,
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),
type,
complication_id,
shared_data->ToString()));
+ delete shared_data;
}
}
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
#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:
const Bundle* context,
Bundle* shared_data) override;
- void NotifyDataUpdate();
+ int NotifyDataUpdate();
const std::string& GetProviderId() const;
private:
#include <math.h>
#include <gio/gio.h>
#include <aul.h>
+#include <aul_complication.h>
+#include <app_control_internal.h>
#include <dlog.h>
+#include <bundle.h>
#include <map>
#include <list>
-#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
shared_data->GetRaw(), user_data_);
}
+ on_update_request_cb GetCallback() {
+ return cb_;
+ }
+
private:
on_update_request_cb cb_;
void* user_data_;
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;
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:
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(
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(
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()) {
}
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(
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) {
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;
}
}
- ComplicationConnector::GetInst().EmitSignal(
+ emit_signal_ret = ComplicationConnector::GetInst().EmitSignal(
ComplicationConnector::Editable,
std::string(editor_appid),
std::string(editor_appid), -1,
free(editable_id);
free(raw_data);
+ if (emit_signal_ret == false)
+ return COMPLICATION_ERROR_IO_ERROR;
+
return COMPLICATION_ERROR_NONE;
}
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;
}
void* user_data) {
IEventListener* rs = static_cast<IEventListener*>(user_data);
- rs->OnSignal(sender_name, object_path, interface_name,
+ rs->OnSignal(connection, sender_name, object_path, interface_name,
signal_name, parameters);
}
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,
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,
}
-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,
}
std::string Complication::Impl::GetProviderAppId() {
- return DBManager::GetProviderAppId(cur_provider_id_);
+ return DBManager::GetProviderAppId(cur_provider_id_.c_str());
}
int Complication::GetComplicationId() {
std::unique_ptr<Bundle> default_data = nullptr;
const char* raw_data;
sqlite3_stmt* stmt;
- sqlite3* db = NULL;
+ sqlite3* db;
int ret;
static const char query[] =
default_data = std::unique_ptr<Bundle>(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 "
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;
int ret;
char *provider_id = NULL;
sqlite3_stmt* stmt;
- sqlite3* db = NULL;
+ sqlite3* db;
std::list<std::string> provider_list;
static const char query[] =
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<std::string> DBManager::GetRequiredPrivlegeList(std::string& provider_id) {
+ int ret;
+ char *privlege = NULL;
+ sqlite3_stmt* stmt;
+ sqlite3* db;
+ std::list<std::string> 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;
public:
static std::unique_ptr<Bundle> 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<std::string> GetProviderList(int support_type);
+ static std::list<std::string> GetRequiredPrivlegeList(std::string& provider_id);
+ static int GetSupportTypes(std::string& provider_id, int* types);
private:
DBManager();
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,
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,
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,
}
-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,