[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 <p.kosko@samsung.com>
} // namespace
-PushInstance::PushInstance(){
+PushInstance::PushInstance() : impl(nullptr) {
LoggerD("Enter");
using std::placeholders::_1;
using std::placeholders::_2;
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(
void PushInstance::unregisterApplication(const picojson::value& args,
picojson::object& out) {
LoggerD("Enter");
+ initApi(PUSH_API_2_4);
CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out);
void PushInstance::connectService(const picojson::value& args,
picojson::object& out) {
LoggerD("Enter");
+ initApi(PUSH_API_3_0);
CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out);
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 {
void PushInstance::getRegistrationId(const picojson::value& args,
picojson::object& out) {
LoggerD("Enter");
+ initApi(PUSH_API_2_4);
CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out);
void PushInstance::getUnreadNotifications(const picojson::value& args,
picojson::object& out) {
LoggerD("Enter");
+ initApi(PUSH_API_2_4);
CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out);
void PushInstance::getPushMessage(const picojson::value& args,
picojson::object& out) {
LoggerD("Enter");
+ initApi(PUSH_API_2_4);
CHECK_PRIVILEGE_ACCESS(kPrivilegePush, &out);
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()) {
PushInstance::~PushInstance() {
LoggerD("Enter");
- delete impl;
+ if (impl) {
+ delete impl;
+ impl = nullptr;
+ }
}
} // namespace push
namespace extension {
namespace push {
+enum ApiVersionType{
+ PUSH_API_2_4,
+ PUSH_API_3_0
+} ;
+
class PushInstance: public common::ParsedInstance, public EventListener {
public:
PushInstance();
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
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<void*>(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);
}
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<PushManagerHolder*>(user_data);
+ // automatically releases memory
+ std::unique_ptr<PushManagerHolder> holder_ptr(holder);
+ PushManager* impl = dynamic_cast<PushManager*>(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<PushManagerHolder*>(user_data);
+ // automatically releases memory
+ PushManager* impl = dynamic_cast<PushManager*>(holder->impl);
+ std::unique_ptr<PushManagerHolder> 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
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
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");
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) {
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
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 {
class PushManagerCommon {
public :
- static common::ErrorCode ConvertPushError(int e);
static std::string GetEncodedBundle();
};
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) {
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() {
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);
}
*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));
}
}
}
}
+// 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
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);
void *user_data);
push_service_state_e m_state;
-
- app_control_h app_control_;
- char* operation_;
bool m_ignoreNotificationEvents;
};