[Widget] Added add/removeChangeListener implementation.
authorTomasz Marciniak <t.marciniak@samsung.com>
Fri, 11 Mar 2016 09:55:03 +0000 (10:55 +0100)
committerLukasz Bardeli <l.bardeli@samsung.com>
Thu, 14 Apr 2016 09:32:16 +0000 (11:32 +0200)
[Verification] Code compiles.

Change-Id: I560338be78c22fddb107e54f1dff10103eadd9b8
Signed-off-by: Tomasz Marciniak <t.marciniak@samsung.com>
src/widget/widget_api.js
src/widget/widget_instance.cc
src/widget/widget_instance.h
src/widget/widget_utils.cc
src/widget/widget_utils.h

index a1c1fdad357e5eb32ee556232d705e1e9aedaa20..f714d287bfecfee7cca7999e39c662dc1ce79f70 100755 (executable)
@@ -36,13 +36,6 @@ var WidgetSizeType = {
   FULL : 'FULL',
 };
 
-var WidgetLifecycleEventType = {
-  CREATE : 'CREATE',
-  DESTROY : 'DESTROY',
-  PAUSE : 'PAUSE',
-  RESUME : 'RESUME',
-};
-
 function createObjects(data, func, widget) {
   var array = [];
   var objects = native.getResultObject(data);
@@ -335,7 +328,7 @@ function ListenerManager(native, listenerName) {
 ListenerManager.prototype.onListenerCalled = function(msg) {
   for (var watchId in this.listeners) {
     if (this.listeners.hasOwnProperty(watchId) && this.listeners[watchId][msg.action]) {
-      this.listeners[watchId][msg.action](msg.id, msg.event);
+      this.listeners[watchId](this.native.getResultObject(msg));
     }
   }
 };
@@ -370,14 +363,18 @@ Widget.prototype.addChangeListener = function() {
     type : types.FUNCTION,
   }]);
 
-  if (T.isEmptyObject(widgetChangeListener.listeners)) {
-    var result = native.callSync('Widget_addChangeListener', {widgetId : this.id});
-    if (native.isFailure(result)) {
-      throw native.getErrorObject(result);
-    }
+  var result = native.callSync('Widget_addChangeListener', {widgetId : this.id});
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
   }
 
-  return widgetChangeListener.addListener(args.eventCallback);
+  var func = function(msg) {
+    if (msg.widgetId === this.id) {
+      args.eventCallback(msg.instanceId, msg.event);
+    }
+  }.bind(this);
+
+  return widgetChangeListener.addListener(func);
 };
 
 Widget.prototype.removeChangeListener = function() {
@@ -388,11 +385,9 @@ Widget.prototype.removeChangeListener = function() {
 
   widgetChangeListener.removeListener(args.watchId);
 
-  if (T.isEmptyObject(widgetChangeListener.listeners)) {
-    var result = native.callSync('Widget_removeChangeListener', {widgetId : this.id});
-    if (native.isFailure(result)) {
-      throw native.getErrorObject(result);
-    }
+  var result = native.callSync('Widget_removeChangeListener', {widgetId : this.id});
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
   }
 };
 
index 36b0c67643c418d6b2ba0817b95419311b286363..120e52d46bd0a6a44e3a92772275b8f547bb5e13 100755 (executable)
@@ -32,7 +32,11 @@ namespace widget {
 using common::TizenResult;
 using common::TizenSuccess;
 
+std::mutex WidgetInstance::listener_mutex_;
+
 namespace {
+const common::ListenerToken kWidgetChangeCallbackToken{"WidgetChangeCallback"};
+
 const std::string kPrivilegeWidget = "http://tizen.org/privilege/widget.viewer";
 
 const std::string kLang = "lang";
@@ -40,6 +44,7 @@ const std::string kInstanceId = "instanceId";
 const std::string kPeriod = "period";
 const std::string kForce = "force";
 const std::string kData = "data";
+const std::string kEvent = "event";
 
 int WidgetListCb(const char* pkgid, const char* widget_id, int is_primary, void* data) {
   ScopeLogger();
@@ -98,6 +103,35 @@ int WidgetInstanceCb(const char* widget_id, const char* instance_id, void* data)
   return WIDGET_ERROR_NONE;
 }
 
+int WidgetLifecycleCb(const char* widget_id, widget_lifecycle_event_e lifecycle_event,
+                      const char* widget_instance_id, void* data) {
+  ScopeLogger();
+
+  //WIDGET_LIFE_CYCLE_EVENT_MAX event is not supported
+  if (WIDGET_LIFE_CYCLE_EVENT_RESUME < lifecycle_event) {
+    LoggerW("Unknown event type");
+    return WIDGET_ERROR_NONE;
+  }
+
+  WidgetInstance* instance = static_cast<WidgetInstance*>(data);
+
+  if (!instance) {
+    LoggerW("User data is null");
+    return WIDGET_ERROR_NONE;
+  }
+
+  picojson::value response = picojson::value(picojson::object());
+  auto& obj = response.get<picojson::object>();
+
+  obj.insert(std::make_pair(kWidgetId, picojson::value(widget_id)));
+  obj.insert(std::make_pair(kInstanceId, picojson::value(widget_instance_id)));
+  obj.insert(std::make_pair(kEvent, picojson::value(WidgetUtils::FromEventType(lifecycle_event))));
+
+  instance->CallWidgetLifecycleListener(widget_id, response);
+
+  return WIDGET_ERROR_NONE;
+}
+
 }  // namespace
 
 WidgetInstance::WidgetInstance() {
@@ -132,6 +166,16 @@ WidgetInstance::WidgetInstance() {
 
 WidgetInstance::~WidgetInstance() {
   ScopeLogger();
+
+  std::lock_guard<std::mutex> lock(listener_mutex_);
+  for (auto& it : listener_map_) {
+    int ret = widget_service_unset_lifecycle_event_cb(it.first.c_str(), nullptr);
+    if (WIDGET_ERROR_NONE != ret) {
+      LoggerE("widget_service_unset_lifecycle_event_cb() failed");
+    }
+  }
+
+  listener_map_.clear();
 }
 
 TizenResult WidgetInstance::GetWidget(const picojson::object& args) {
@@ -140,7 +184,7 @@ TizenResult WidgetInstance::GetWidget(const picojson::object& args) {
   //CHECK_PRIVILEGE_ACCESS(kPrivilegeWidget, &out);
   CHECK_EXIST(args, kWidgetId, out)
 
-  std::string widget_id = args.find(kWidgetId)->second.get<std::string>();
+  const auto& widget_id = args.find(kWidgetId)->second.get<std::string>();
 
   picojson::value value {picojson::object{}};
   auto* obj = &value.get<picojson::object>();
@@ -199,7 +243,7 @@ TizenResult WidgetInstance::GetPrimaryWidgetId(const picojson::object& args) {
   //CHECK_PRIVILEGE_ACCESS(kPrivilegeWidget, &out);
   CHECK_EXIST(args, kId, out)
 
-  std::string id = args.find(kId)->second.get<std::string>();
+  const auto& id = args.find(kId)->second.get<std::string>();
 
   char* widget_id = widget_service_get_widget_id(id.c_str());
   if (!widget_id) {
@@ -331,7 +375,7 @@ TizenResult WidgetInstance::GetVariants(picojson::object const& args, const comm
   //CHECK_PRIVILEGE_ACCESS(kPrivilegeWidget, &out);
   CHECK_EXIST(args, kWidgetId, out)
 
-  std::string widget_id = args.find(kWidgetId)->second.get<std::string>();
+  const auto& widget_id = args.find(kWidgetId)->second.get<std::string>();
 
   auto get_variants = [this, widget_id](const common::AsyncToken& token) -> void {
     int count = 0;
@@ -386,16 +430,70 @@ TizenResult WidgetInstance::GetVariants(picojson::object const& args, const comm
   return TizenSuccess();
 }
 
+void WidgetInstance::CallWidgetLifecycleListener(const std::string& widget_id,
+                                                 const picojson::value& response) {
+  ScopeLogger();
+
+  std::lock_guard<std::mutex> lock(listener_mutex_);
+  const auto it = listener_map_.find(widget_id);
+  if (listener_map_.end() != it) {
+    Post(kWidgetChangeCallbackToken, TizenSuccess{response});
+    return;
+  }
+
+  LoggerW("widget id was not found.");
+}
+
 TizenResult WidgetInstance::AddChangeListener(picojson::object const& args) {
   ScopeLogger();
 
-  return common::NotSupportedError();
+  //CHECK_PRIVILEGE_ACCESS(kPrivilegeWidget, &out);
+  CHECK_EXIST(args, kWidgetId, out)
+
+  const auto& widget_id = args.find(kWidgetId)->second.get<std::string>();
+
+  std::lock_guard<std::mutex> lock(listener_mutex_);
+  auto it = listener_map_.find(widget_id);
+  if (listener_map_.end() != it) {
+    it->second++;
+    return TizenSuccess();
+  }
+
+  int ret = widget_service_set_lifecycle_event_cb(widget_id.c_str(), WidgetLifecycleCb , this);
+  if (WIDGET_ERROR_NONE != ret) {
+    LogAndReturnTizenError(
+        WidgetUtils::ConvertErrorCode(ret), ("widget_service_set_lifecycle_event_cb() failed"));
+  }
+
+  listener_map_[widget_id]++;
+
+  return TizenSuccess();
 }
 
 TizenResult WidgetInstance::RemoveChangeListener(picojson::object const& args) {
   ScopeLogger();
 
-  return common::NotSupportedError();
+  CHECK_EXIST(args, kWidgetId, out)
+
+  const auto& widget_id = args.find(kWidgetId)->second.get<std::string>();
+
+  std::lock_guard<std::mutex> lock(listener_mutex_);
+  auto it = listener_map_.find(widget_id);
+  if (listener_map_.end() == it) {
+    LoggerW("Listener id not found");
+    return TizenSuccess();
+  }
+
+  if (!(--it->second)) {
+    int ret = widget_service_unset_lifecycle_event_cb(widget_id.c_str(), nullptr);
+    if (WIDGET_ERROR_NONE != ret) {
+      LogAndReturnTizenError(
+          WidgetUtils::ConvertErrorCode(ret), ("widget_service_unset_lifecycle_event_cb() failed"));
+    }
+    listener_map_.erase(it);
+  }
+
+  return TizenSuccess();
 }
 
 TizenResult WidgetInstance::ChangeUpdatePeriod(picojson::object const& args) {
index f19cfd8f087e12397f544145175b944cde59457c..313421cde3bbc1f458cb5f82e484783b42ea5d81 100755 (executable)
@@ -17,6 +17,9 @@
 #ifndef WIDGET_WIDGET_INSTANCE_H_
 #define WIDGET_WIDGET_INSTANCE_H_
 
+#include <mutex>
+#include <map>
+
 #include "common/tizen_instance.h"
 
 namespace extension {
@@ -26,7 +29,7 @@ class WidgetInstance : public common::TizenInstance {
  public:
   WidgetInstance();
   virtual ~WidgetInstance();
-
+  void CallWidgetLifecycleListener(const std::string& widget_id, const picojson::value& response);
  private:
   //WidgetManager
   common::TizenResult GetWidget(picojson::object const& args);
@@ -45,6 +48,8 @@ class WidgetInstance : public common::TizenInstance {
   common::TizenResult SendContent(picojson::object const& args);
   common::TizenResult GetContent(picojson::object const& args, const common::AsyncToken& token);
 
+  static std::mutex listener_mutex_;
+  std::map<std::string, int> listener_map_;
 };
 
 } // namespace widget
index 66b8aaeca7011263bfa21f80a831934bfffb1800..41de85c92b7b6c3e540c93fe4ac2010e04fa2456 100644 (file)
@@ -39,6 +39,13 @@ namespace {
   X(WIDGET_SIZE_TYPE_FULL, "FULL") \
   XD(WIDGET_SIZE_TYPE_UNKNOWN, "unknown")
 
+#define WIDGET_LIFECYCLE_EVENT_E \
+  X(WIDGET_LIFE_CYCLE_EVENT_CREATE, "CREATE") \
+  X(WIDGET_LIFE_CYCLE_EVENT_DESTROY, "DESTROY") \
+  X(WIDGET_LIFE_CYCLE_EVENT_PAUSE, "PAUSE") \
+  X(WIDGET_LIFE_CYCLE_EVENT_RESUME, "RESUME") \
+  XD(WIDGET_LIFE_CYCLE_EVENT_MAX, "unknown")
+
 } // namespace
 
 const std::string kWidgetId = "widgetId";
@@ -210,6 +217,14 @@ std::string WidgetUtils::FromSizeType(widget_size_type_e e) {
   }
 }
 
+std::string WidgetUtils::FromEventType(widget_lifecycle_event_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    WIDGET_LIFECYCLE_EVENT_E
+  }
+}
+
 #undef X
 #undef XD
 
index 1539e079e801e69431b64ce86cdfcef4710be1e3..a82eedebc5467e8d4c4e691046f5e9688a1c0a6e 100644 (file)
@@ -42,6 +42,7 @@ class WidgetUtils {
  public:
   static widget_size_type_e ToSizeType(const std::string& e);
   static std::string FromSizeType(widget_size_type_e e);
+  static std::string FromEventType(widget_lifecycle_event_e e);
   static common::TizenResult ConvertErrorCode(int error);
   static common::TizenResult WidgetToJson(const char* id, picojson::object* out, const char* pkgid = nullptr);
   static common::TizenResult SizeToJson(widget_size_type_e type, picojson::object* out);