From: Tomasz Marciniak Date: Fri, 11 Mar 2016 09:55:03 +0000 (+0100) Subject: [Widget] Added add/removeChangeListener implementation. X-Git-Tag: submit/tizen/20160418.070226^2~3^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=72a954dacb2cb5e39609871a1592a04992c8e311;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Widget] Added add/removeChangeListener implementation. [Verification] Code compiles. Change-Id: I560338be78c22fddb107e54f1dff10103eadd9b8 Signed-off-by: Tomasz Marciniak --- diff --git a/src/widget/widget_api.js b/src/widget/widget_api.js index a1c1fdad..f714d287 100755 --- a/src/widget/widget_api.js +++ b/src/widget/widget_api.js @@ -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); } }; diff --git a/src/widget/widget_instance.cc b/src/widget/widget_instance.cc index 36b0c676..120e52d4 100755 --- a/src/widget/widget_instance.cc +++ b/src/widget/widget_instance.cc @@ -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(data); + + if (!instance) { + LoggerW("User data is null"); + return WIDGET_ERROR_NONE; + } + + picojson::value response = picojson::value(picojson::object()); + auto& obj = response.get(); + + 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 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(); + const auto& widget_id = args.find(kWidgetId)->second.get(); picojson::value value {picojson::object{}}; auto* obj = &value.get(); @@ -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(); + const auto& id = args.find(kId)->second.get(); 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(); + const auto& widget_id = args.find(kWidgetId)->second.get(); 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 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::lock_guard 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::lock_guard 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) { diff --git a/src/widget/widget_instance.h b/src/widget/widget_instance.h index f19cfd8f..313421cd 100755 --- a/src/widget/widget_instance.h +++ b/src/widget/widget_instance.h @@ -17,6 +17,9 @@ #ifndef WIDGET_WIDGET_INSTANCE_H_ #define WIDGET_WIDGET_INSTANCE_H_ +#include +#include + #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 listener_map_; }; } // namespace widget diff --git a/src/widget/widget_utils.cc b/src/widget/widget_utils.cc index 66b8aaec..41de85c9 100644 --- a/src/widget/widget_utils.cc +++ b/src/widget/widget_utils.cc @@ -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 diff --git a/src/widget/widget_utils.h b/src/widget/widget_utils.h index 1539e079..a82eedeb 100644 --- a/src/widget/widget_utils.h +++ b/src/widget/widget_utils.h @@ -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);