[Push] implementation of new manager version 36/86336/8
authorPiotr Kosko <p.kosko@samsung.com>
Wed, 31 Aug 2016 13:33:10 +0000 (15:33 +0200)
committertaekeun.kang <taekeun.kang@samsung.com>
Tue, 1 Nov 2016 08:43:14 +0000 (17:43 +0900)
[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>
src/push/push_instance.cc
src/push/push_instance.h
src/push/push_manager.cc
src/push/push_manager.h
src/push/push_manager_common.cc
src/push/push_manager_common.h
src/push/push_manager_old.cc
src/push/push_manager_old.h

index 374850e..9818b80 100644 (file)
@@ -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
index 9d342f3..8b08c4d 100644 (file)
 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
index ce6051b..3b55632 100644 (file)
@@ -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<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, &notification);
+  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<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
 
index a91a1c4..bd5863a 100644 (file)
@@ -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
index d711ca3..f8605aa 100644 (file)
@@ -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
 
index 6d41116..d7121d2 100644 (file)
@@ -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();
 };
 
index 1b67bfa..e9a2091 100644 (file)
@@ -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
 
index c5a2aae..9c9deb7 100644 (file)
@@ -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;
 };