From 5334d85060fd52a87e03a89d548ef0b162208759 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Wed, 31 Aug 2016 15:33:10 +0200 Subject: [PATCH] [Push] implementation of new manager version [Feature] Added implementation of new version of API. Both scenarios for push service are possible: 1. connect -> register (3.0 API) 2. register -> connect (before 3.0 API) [Verification] Code compiles without errors. TCT passrate didn't change. Change-Id: I17cb8d75775b4f0a2a193a102700a853213afa49 Signed-off-by: Piotr Kosko --- src/push/push_instance.cc | 36 ++++++--- src/push/push_instance.h | 24 +++--- src/push/push_manager.cc | 129 +++++++++++++++++++++++++++++++- src/push/push_manager.h | 4 + src/push/push_manager_common.cc | 89 ++++++++++++++++------ src/push/push_manager_common.h | 5 +- src/push/push_manager_old.cc | 77 +++++++------------ src/push/push_manager_old.h | 9 +-- 8 files changed, 272 insertions(+), 101 deletions(-) diff --git a/src/push/push_instance.cc b/src/push/push_instance.cc index 374850e7..9818b80f 100644 --- a/src/push/push_instance.cc +++ b/src/push/push_instance.cc @@ -31,7 +31,7 @@ const std::string kPrivilegePush = "http://tizen.org/privilege/push"; } // namespace -PushInstance::PushInstance(){ +PushInstance::PushInstance() : impl(nullptr) { LoggerD("Enter"); using std::placeholders::_1; using std::placeholders::_2; @@ -56,21 +56,29 @@ PushInstance::PushInstance(){ REGISTER_SYNC("Push_getPushMessage", std::bind(&PushInstance::getPushMessage, this, _1, _2)); - if (common::tools::IsAppVersionEarlierThan("3.0")) { - LoggerD("Application version is earlier than 3.0, use previous API"); + #undef REGISTER_ASYNC + #undef REGISTER_SYNC +} + +void PushInstance::initApi(ApiVersionType type) { + LoggerD("Enter"); + if (!impl) { + if (PUSH_API_2_4 == type) { + LoggerD("No API already initialized - using Tizen 2.4 API"); impl = new PushManagerOld(this); } else { - LoggerD("Application version is 3.0 or later, use new API"); + LoggerD("No API already initialized - using Tizen 3.0 API"); impl = new PushManager(this); } - - #undef REGISTER_ASYNC - #undef REGISTER_SYNC + } else { + LoggerD("API already initialized - use currently initialized API"); + } } void PushInstance::registerApplication(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); common::PlatformResult result = impl->registerApplication( @@ -85,6 +93,7 @@ void PushInstance::registerApplication(const picojson::value& args, void PushInstance::unregisterApplication(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); @@ -100,6 +109,7 @@ void PushInstance::unregisterApplication(const picojson::value& args, void PushInstance::connectService(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_3_0); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); @@ -114,10 +124,11 @@ void PushInstance::connectService(const picojson::value& args, void PushInstance::disconnectService(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); - common::PlatformResult result = impl->connectService(); + common::PlatformResult result = impl->disconnectService(); if (result.IsError()) { LogAndReportError(result, &out, ("Error while disconnect service")); } else { @@ -129,6 +140,7 @@ void PushInstance::disconnectService(const picojson::value& args, void PushInstance::getRegistrationId(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); @@ -147,6 +159,7 @@ void PushInstance::getRegistrationId(const picojson::value& args, void PushInstance::getUnreadNotifications(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); @@ -161,6 +174,7 @@ void PushInstance::getUnreadNotifications(const picojson::value& args, void PushInstance::getPushMessage(const picojson::value& args, picojson::object& out) { LoggerD("Enter"); + initApi(PUSH_API_2_4); CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out); @@ -177,7 +191,6 @@ void PushInstance::getPushMessage(const picojson::value& args, void PushInstance::onPushRegister(double callbackId, common::PlatformResult result, const std::string& id) { - LoggerD("Enter"); picojson::value::object dict; dict["callbackId"] = picojson::value(callbackId); if (result.IsError()) { @@ -215,7 +228,10 @@ void PushInstance::onDeregister(double callbackId, PushInstance::~PushInstance() { LoggerD("Enter"); - delete impl; + if (impl) { + delete impl; + impl = nullptr; + } } } // namespace push diff --git a/src/push/push_instance.h b/src/push/push_instance.h index 9d342f38..8b08c4d9 100644 --- a/src/push/push_instance.h +++ b/src/push/push_instance.h @@ -24,6 +24,11 @@ namespace extension { namespace push { +enum ApiVersionType{ + PUSH_API_2_4, + PUSH_API_3_0 +} ; + class PushInstance: public common::ParsedInstance, public EventListener { public: PushInstance(); @@ -34,15 +39,16 @@ class PushInstance: public common::ParsedInstance, public EventListener { virtual void onDeregister(double callbackId, common::PlatformResult result); private: - void registerApplication(const picojson::value& args, picojson::object& out); - void unregisterApplication(const picojson::value& args, picojson::object& out); - void connectService(const picojson::value& args, picojson::object& out); - void disconnectService(const picojson::value& args, picojson::object& out); - void getRegistrationId(const picojson::value& args, picojson::object& out); - void getUnreadNotifications(const picojson::value& args, picojson::object& out); - void getPushMessage(const picojson::value& args, picojson::object& out); - - IPushManager* impl; + void registerApplication(const picojson::value& args, picojson::object& out); + void unregisterApplication(const picojson::value& args, picojson::object& out); + void connectService(const picojson::value& args, picojson::object& out); + void disconnectService(const picojson::value& args, picojson::object& out); + void getRegistrationId(const picojson::value& args, picojson::object& out); + void getUnreadNotifications(const picojson::value& args, picojson::object& out); + void getPushMessage(const picojson::value& args, picojson::object& out); + void initApi(ApiVersionType type); + + IPushManager* impl; }; } // namespace push diff --git a/src/push/push_manager.cc b/src/push/push_manager.cc index ce6051b2..3b55632d 100644 --- a/src/push/push_manager.cc +++ b/src/push/push_manager.cc @@ -47,40 +47,100 @@ PlatformResult PushManager::connectService() { int ret = push_service_connect(m_pkgId.c_str(), onPushState, onPushNotify, this, &m_handle); - if (ret != PUSH_SERVICE_ERROR_NONE) { - LoggerE("Failed to connect to push (%d)", ret); + if (PUSH_SERVICE_ERROR_NONE != ret) { + return LogAndCreateResult(ConvertPushError(ret), "Failed to connect to push service", + ("push_service_connect failed (%d)", ret)); } return common::PlatformResult(ErrorCode::NO_ERROR); } PlatformResult PushManager::disconnectService() { LoggerD("Enter"); + if (m_handle) { + push_service_disconnect(m_handle); + m_handle = nullptr; + } return common::PlatformResult(ErrorCode::NO_ERROR); } PlatformResult PushManager::registerApplication(double callbackId) { LoggerD("Enter"); + + PushManagerHolder* holder = new PushManagerHolder{this, callbackId}; + + int ret = push_service_register(m_handle, onApplicationRegister, static_cast(holder)); + if (PUSH_SERVICE_ERROR_NONE != ret) { + delete holder; + + return LogAndCreateResult(ConvertPushError(ret), "Failed to register", + ("push_service_register failed (%d)", ret)); + } return common::PlatformResult(ErrorCode::NO_ERROR); } common::PlatformResult PushManager::unregisterApplication(double callbackId) { LoggerD("Enter"); + PushManagerHolder* holder = new PushManagerHolder{this, callbackId}; + + int ret = push_service_deregister(m_handle, onDeregister, holder); + if (PUSH_SERVICE_ERROR_NONE != ret) { + delete holder; + return LogAndCreateResult(ConvertPushError(ret), "Failed to deregister", + ("push_service_deregister failed (%d)", ret)); + } + return common::PlatformResult(ErrorCode::NO_ERROR); } common::PlatformResult PushManager::getRegistrationId(std::string& id) { LoggerD("Enter"); + char* temp = nullptr; + int ret = push_service_get_registration_id(m_handle, &temp); + if (PUSH_SERVICE_ERROR_NONE != ret) { + return LogAndCreateResult(ConvertPushError(ret), "Failed to get registration id", + ("push_service_get_registration_id failed (%d)", ret)); + } + id = temp; + free(temp); return common::PlatformResult(ErrorCode::NO_ERROR); } common::PlatformResult PushManager::getUnreadNotifications() { LoggerD("Enter"); + int ret = push_service_request_unread_notification(m_handle); + if (PUSH_SERVICE_ERROR_NONE != ret) { + return LogAndCreateResult(ConvertPushError(ret), "Failed to get unread notifications", + ("push_service_request_unread_notification failed (%d)", ret)); + } return common::PlatformResult(ErrorCode::NO_ERROR); } PlatformResult PushManager::getPushMessage(picojson::value* out) { LoggerD("Enter"); + push_service_notification_h handle = nullptr; + int ret = push_service_app_control_to_notification(app_control_, operation_, + &handle); + + if (PUSH_SERVICE_ERROR_NONE != ret) { + if (PUSH_SERVICE_ERROR_NO_DATA == ret || PUSH_SERVICE_ERROR_NOT_SUPPORTED == ret) { + LoggerD("ret: %s", ConvertPushError(ret)); + // application was not started by push service, return null + *out = picojson::value{}; + return common::PlatformResult(ErrorCode::NO_ERROR); + } else { + // return AbortError for other error types + return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get push message for application", + ("push_service_app_control_to_notification failed (%d)", ret)); + } + } + + picojson::object notification; + notificationToJson(handle, ¬ification); + push_service_free_notification(handle); + + *out = picojson::value{notification}; + return common::PlatformResult(ErrorCode::NO_ERROR); } @@ -99,6 +159,71 @@ void PushManager::onPushNotify(push_service_notification_h noti, void* user_data impl->m_listener->onPushNotify(noti); } +void PushManager::onApplicationRegister(push_service_result_e result, const char* msg, void* user_data) { + LoggerD("Enter"); + + PushManagerHolder* holder = static_cast(user_data); + // automatically releases memory + std::unique_ptr holder_ptr(holder); + PushManager* impl = dynamic_cast(holder->impl); + double callbackId = holder->callbackId; + + if (nullptr == impl || !impl->m_listener) { + LoggerW("Listener not set, ignoring"); + return; + } + + std::string id; + PlatformResult res(ErrorCode::NO_ERROR); + + if (PUSH_SERVICE_RESULT_SUCCESS == result) { + LoggerD("Success"); + char *temp = nullptr; + int ret = push_service_get_registration_id(impl->m_handle, &temp); + if (PUSH_SERVICE_ERROR_NONE == ret) { + LoggerD("Registration id retrieved"); + id = temp; + free(temp); + } else { + res = LogAndCreateResult( + ErrorCode::ABORT_ERR, "Failed to retrieve registration id", + ("Failed to retrieve registration id: push_service_get_registration_id(%d)", ret)); + } + } else { + if (PUSH_SERVICE_RESULT_TIMEOUT == result) { + LoggerE("PUSH_SERVICE_RESULT_TIMEOUT"); + } else if (PUSH_SERVICE_RESULT_SERVER_ERROR == result) { + LoggerE("PUSH_SERVICE_RESULT_SERVER_ERROR"); + } else if (PUSH_SERVICE_RESULT_SYSTEM_ERROR == result) { + LoggerE("PUSH_SERVICE_RESULT_SYSTEM_ERROR"); + } + res = LogAndCreateResult(ErrorCode::ABORT_ERR, nullptr == msg ? "Abort error" : msg); + } + + impl->m_listener->onPushRegister(callbackId, res, id); +} + +void PushManager::onDeregister(push_service_result_e result, const char* msg, + void* user_data) { + LoggerD("Enter"); + PushManagerHolder* holder = static_cast(user_data); + // automatically releases memory + PushManager* impl = dynamic_cast(holder->impl); + std::unique_ptr holder_ptr(holder); + double callbackId = holder->callbackId; + + if (nullptr == impl || !impl->m_listener) { + LoggerW("Listener not set, ignoring"); + return; + } + if (PUSH_SERVICE_RESULT_SUCCESS == result) { + impl->m_listener->onDeregister(callbackId, PlatformResult(ErrorCode::NO_ERROR)); + } else { + impl->m_listener->onDeregister(callbackId, LogAndCreateResult(ErrorCode::ABORT_ERR, + msg == nullptr ? "Unknown error" : msg)); + } +} + } // namespace push } // namespace extension diff --git a/src/push/push_manager.h b/src/push/push_manager.h index a91a1c4c..bd5863af 100644 --- a/src/push/push_manager.h +++ b/src/push/push_manager.h @@ -44,6 +44,10 @@ class PushManager : public IPushManager { static void onPushState(push_service_state_e state, const char *err, void *user_data); static void onPushNotify(push_service_notification_h noti, void *user_data); + static void onApplicationRegister(push_service_result_e result, const char *msg, + void *user_data); + static void onDeregister(push_service_result_e result, const char *msg, + void *user_data); }; } // namespace push diff --git a/src/push/push_manager_common.cc b/src/push/push_manager_common.cc index d711ca33..f8605aae 100644 --- a/src/push/push_manager_common.cc +++ b/src/push/push_manager_common.cc @@ -32,29 +32,6 @@ namespace push { using common::PlatformResult; using common::ErrorCode; -ErrorCode PushManagerCommon::ConvertPushError(int e) { - ErrorCode error; - - switch(e) { - case PUSH_SERVICE_ERROR_NONE: - error = ErrorCode::NO_ERROR; - break; - - case PUSH_SERVICE_ERROR_INVALID_PARAMETER: - error = ErrorCode::INVALID_VALUES_ERR; - break; - - case PUSH_SERVICE_ERROR_OUT_OF_MEMORY: - case PUSH_SERVICE_ERROR_NOT_CONNECTED: - case PUSH_SERVICE_ERROR_OPERATION_FAILED: - default: - error = ErrorCode::ABORT_ERR; - break; - } - - return error; -} - std::string PushManagerCommon::GetEncodedBundle() { LoggerD("Entered"); @@ -73,14 +50,30 @@ std::string PushManagerCommon::GetEncodedBundle() { IPushManager::IPushManager(EventListener* listener) : m_listener (listener), - m_handle (nullptr) { + m_handle (nullptr), + app_control_(nullptr), + operation_(nullptr) { LoggerD("Enter"); initPkgId(); + InitAppControl(); } IPushManager::~IPushManager() { LoggerD("Enter"); m_listener = nullptr; + + if (m_handle) { + push_service_disconnect(m_handle); + m_handle = nullptr; + } + + if (app_control_ && (APP_CONTROL_ERROR_NONE != app_control_destroy(app_control_))) { + LoggerE("Failed to destroy app control"); + } + + if (operation_) { + free(operation_); + } } void IPushManager::notificationToJson(push_service_notification_h noti, picojson::object* obj) { @@ -189,6 +182,54 @@ void IPushManager::initPkgId() { app_info_destroy(info); } +void IPushManager::InitAppControl() { + LoggerD("Enter"); + + const auto encoded_bundle = PushManagerCommon::GetEncodedBundle(); + + auto bundle = bundle_decode((bundle_raw*) (encoded_bundle.c_str()), + encoded_bundle.length()); + if (nullptr == bundle) { + LoggerE("Failed to decode bundle"); + return; + } + + int ret = app_control_create_event(bundle, &app_control_); + bundle_free(bundle); + + if (APP_CONTROL_ERROR_NONE != ret) { + LoggerE("app_control_create_event() failed: %d (%s)", ret, get_error_message(ret)); + } else { + ret = app_control_get_operation(app_control_, &operation_); + if (APP_CONTROL_ERROR_NONE != ret) { + LoggerE("app_control_get_operation() failed: %d (%s)", ret, get_error_message(ret)); + } + } +} + +// new version errors mappings, to check mappings for *_old impl, check overloaded method +ErrorCode IPushManager::ConvertPushError(int e) { + LoggerD("Enter"); + ErrorCode error; + + switch(e) { + case PUSH_SERVICE_ERROR_NONE: + error = ErrorCode::NO_ERROR; + break; + case PUSH_SERVICE_ERROR_INVALID_PARAMETER: + case PUSH_SERVICE_ERROR_NOT_CONNECTED: + case PUSH_SERVICE_ERROR_NOT_SUPPORTED: + error = ErrorCode::INVALID_STATE_ERR; + break; + default: + error = ErrorCode::ABORT_ERR; + break; + } + + return error; +} + + } // namespace push } // namespace extension diff --git a/src/push/push_manager_common.h b/src/push/push_manager_common.h index 6d411167..d7121d28 100644 --- a/src/push/push_manager_common.h +++ b/src/push/push_manager_common.h @@ -53,10 +53,14 @@ class IPushManager { void notificationToJson(push_service_notification_h noti, picojson::object* obj); protected : void initPkgId(); + void InitAppControl(); + static common::ErrorCode ConvertPushError(int e); EventListener* m_listener; push_service_connection_h m_handle; std::string m_pkgId; + app_control_h app_control_; + char* operation_; }; struct PushManagerHolder { @@ -66,7 +70,6 @@ struct PushManagerHolder { class PushManagerCommon { public : - static common::ErrorCode ConvertPushError(int e); static std::string GetEncodedBundle(); }; diff --git a/src/push/push_manager_old.cc b/src/push/push_manager_old.cc index 1b67bfa9..e9a20918 100644 --- a/src/push/push_manager_old.cc +++ b/src/push/push_manager_old.cc @@ -36,13 +36,8 @@ using common::ErrorCode; PushManagerOld::PushManagerOld(EventListener* listener) : IPushManager(listener), m_state(PUSH_SERVICE_STATE_UNREGISTERED), - app_control_(nullptr), - operation_(nullptr), m_ignoreNotificationEvents (true) { LoggerD("Enter"); - - InitAppControl(); - int ret = push_service_connect(m_pkgId.c_str(), onPushState, onPushNotify, this, &m_handle); if (ret != PUSH_SERVICE_ERROR_NONE) { @@ -52,45 +47,6 @@ PushManagerOld::PushManagerOld(EventListener* listener) : PushManagerOld::~PushManagerOld() { LoggerD("Enter"); - - if (m_handle) { - push_service_disconnect(m_handle); - } - - if (app_control_ && (APP_CONTROL_ERROR_NONE != app_control_destroy(app_control_))) { - LoggerE("Failed to destroy app control"); - } - - if (operation_) { - free(operation_); - } -} - -void PushManagerOld::InitAppControl() { - ScopeLogger(); - - const auto encoded_bundle = PushManagerCommon::GetEncodedBundle(); - - auto bundle = bundle_decode((bundle_raw*) (encoded_bundle.c_str()), - encoded_bundle.length()); - if (nullptr == bundle) { - LoggerE("Failed to decode bundle"); - return; - } - - app_control_h app_control = nullptr; - int ret = app_control_create_event(bundle, &app_control); - bundle_free(bundle); - - if (APP_CONTROL_ERROR_NONE != ret) { - LoggerE("app_control_create_event() failed: %d (%s)", ret, get_error_message(ret)); - } else { - app_control_ = app_control; - ret = app_control_get_operation(app_control, &operation_); - if (APP_CONTROL_ERROR_NONE != ret) { - LoggerE("app_control_get_operation() failed: %d (%s)", ret, get_error_message(ret)); - } - } } PlatformResult PushManagerOld::connectService() { @@ -115,8 +71,8 @@ PlatformResult PushManagerOld::registerApplication(double callbackId) { if (ret != PUSH_SERVICE_ERROR_NONE) { delete holder; - return LogAndCreateResult(PushManagerCommon::ConvertPushError(ret), - "Failed to register", ("push_service_register failed (%d)", ret)); + return LogAndCreateResult(ConvertPushError(ret), "Failed to register", + ("push_service_register failed (%d)", ret)); } return common::PlatformResult(ErrorCode::NO_ERROR); } @@ -198,9 +154,8 @@ PlatformResult PushManagerOld::getPushMessage(picojson::value* out) { *out = picojson::value{}; return common::PlatformResult(ErrorCode::NO_ERROR); } else { - return LogAndCreateResult( - PushManagerCommon::ConvertPushError(ret), "Failed to get message", - ("push_service_app_control_to_notification failed: (%d)", ret)); + return LogAndCreateResult(ConvertPushError(ret), "Failed to get message", + ("push_service_app_control_to_notification failed: (%d)", ret)); } } @@ -320,6 +275,30 @@ void PushManagerOld::onDeregister(push_service_result_e result, const char* msg, } } +// Different error code mappings for previous implementation +ErrorCode PushManagerOld::ConvertPushError(int e) { + LoggerD("Enter"); + ErrorCode error; + + switch(e) { + case PUSH_SERVICE_ERROR_NONE: + error = ErrorCode::NO_ERROR; + break; + + case PUSH_SERVICE_ERROR_INVALID_PARAMETER: + error = ErrorCode::INVALID_VALUES_ERR; + break; + + case PUSH_SERVICE_ERROR_OUT_OF_MEMORY: + case PUSH_SERVICE_ERROR_NOT_CONNECTED: + case PUSH_SERVICE_ERROR_OPERATION_FAILED: + default: + error = ErrorCode::ABORT_ERR; + break; + } + return error; +} + } // namespace push } // namespace extension diff --git a/src/push/push_manager_old.h b/src/push/push_manager_old.h index c5a2aae7..9c9deb7c 100644 --- a/src/push/push_manager_old.h +++ b/src/push/push_manager_old.h @@ -41,10 +41,10 @@ class PushManagerOld : public IPushManager { common::PlatformResult getUnreadNotifications(); common::PlatformResult getPushMessage(picojson::value* out); - private: - void initAppId(); - void InitAppControl(); + protected: + static common::ErrorCode ConvertPushError(int e); + private: static void onPushState(push_service_state_e state, const char *err, void *user_data); static void onPushNotify(push_service_notification_h noti, void *user_data); @@ -55,9 +55,6 @@ class PushManagerOld : public IPushManager { void *user_data); push_service_state_e m_state; - - app_control_h app_control_; - char* operation_; bool m_ignoreNotificationEvents; }; -- 2.34.1