From: Andrzej Popowski Date: Mon, 4 Apr 2016 13:11:23 +0000 (+0200) Subject: [Preference] - getAll function implemented X-Git-Tag: submit/tizen/20160418.070226^2~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f37b8179ca77fc1e2c787701ff474ba08d152ce7;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Preference] - getAll function implemented [Features] Added fix for registered listeners. [Verification] Code compiles. Change-Id: I195900bb5495b609f47536d7069f5abdafdd1bd1 Signed-off-by: Andrzej Popowski --- diff --git a/src/preference/preference_api.js b/src/preference/preference_api.js index 9ddd75e9..23434021 100644 --- a/src/preference/preference_api.js +++ b/src/preference/preference_api.js @@ -20,13 +20,27 @@ var type_ = xwalk.utils.type; var types_ = validator_.Types; var native_ = new xwalk.utils.NativeManager(extension); - function PreferenceManager() { } - PreferenceManager.prototype.getAll = function() { - // ... + var args = validator_.validateArgs(arguments, [ + { name: 'successCallback', type: types_.FUNCTION }, + { name: 'errorCallback', type: types_.FUNCTION, optional : true, nullable : true } + ]); + + var callback = function(result) { + if (native_.isFailure(result)) { + native_.callIfPossible(args.errorCallback, native_.getErrorObject(result)); + } else { + args.successCallback(native_.getResultObject(result)); + } + }; + + var result = native_.call('PreferenceManager_getAll', {}, callback); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } }; PreferenceManager.prototype.setValue = function() { @@ -47,7 +61,6 @@ PreferenceManager.prototype.setValue = function() { } }; - PreferenceManager.prototype.getValue = function() { var args = validator_.validateArgs(arguments, [ { name: 'key', type: types_.STRING } @@ -62,7 +75,6 @@ PreferenceManager.prototype.getValue = function() { } }; - PreferenceManager.prototype.remove = function() { var args = validator_.validateArgs(arguments, [ { name: 'key', type: types_.STRING } @@ -75,7 +87,6 @@ PreferenceManager.prototype.remove = function() { } }; - PreferenceManager.prototype.removeAll = function() { var result = native_.callSync('PreferenceManager_removeAll', {}); @@ -84,7 +95,6 @@ PreferenceManager.prototype.removeAll = function() { } }; - PreferenceManager.prototype.exists = function() { var args = validator_.validateArgs(arguments, [ { name: 'key', type: types_.STRING } @@ -99,11 +109,9 @@ PreferenceManager.prototype.exists = function() { } }; +var PREFERENCE_CHANGED_LISTENER = 'PREFERENCE_CHANGED'; -var PREFERENCE_LISTENER = 'PREFERENCE_CHANGED'; - - -function PreferenceListeners() { +function PreferenceChangedListener() { var that = this; this.appListener = function (result) { var data = native_.getResultObject(result); @@ -119,31 +127,26 @@ function PreferenceListeners() { }; } +PreferenceChangedListener.prototype.instances = {}; -PreferenceListeners.prototype.instances = {}; - - -PreferenceListeners.prototype.addListener = function(key, listener) { +PreferenceChangedListener.prototype.addListener = function(key, listener) { if (type_.isEmptyObject(this.instances)) { - native_.addListener(PREFERENCE_LISTENER, this.appListener); + native_.addListener(PREFERENCE_CHANGED_LISTENER, this.appListener); } this.instances[key] = listener; }; - -PreferenceListeners.prototype.removeListener = function(key) { +PreferenceChangedListener.prototype.removeListener = function(key) { if (this.instances[key]) { delete this.instances[key]; if (type_.isEmptyObject(this.instances)) { - native_.removeListener(PREFERENCE_LISTENER); + native_.removeListener(PREFERENCE_CHANGED_LISTENER); } } }; - -var _preferenceListeners = new PreferenceListeners(); - +var _preferenceChangedListener = new PreferenceChangedListener(); PreferenceManager.prototype.setChangeListener = function() { var args = validator_.validateArgs(arguments, [ @@ -156,10 +159,9 @@ PreferenceManager.prototype.setChangeListener = function() { throw native_.getErrorObject(result); } - _preferenceListeners.addListener(args.key, args.listener); + _preferenceChangedListener.addListener(args.key, args.listener); } - PreferenceManager.prototype.unsetChangeListener = function() { var args = validator_.validateArgs(arguments, [ { name: 'key', type: types_.STRING } @@ -171,10 +173,9 @@ PreferenceManager.prototype.unsetChangeListener = function() { throw native_.getErrorObject(result); } - _preferenceListeners.removeListener(args.key); + _preferenceChangedListener.removeListener(args.key); }; - // Exports exports = new PreferenceManager(); diff --git a/src/preference/preference_instance.cc b/src/preference/preference_instance.cc index 1b6d2c52..851689ba 100644 --- a/src/preference/preference_instance.cc +++ b/src/preference/preference_instance.cc @@ -28,6 +28,7 @@ namespace preference { namespace { const char* kKey = "key"; const char* kValue = "value"; + const common::ListenerToken kPreferenceChangeListenerToken{"PREFERENCE_CHANGED"}; } // namespace @@ -66,8 +67,8 @@ PreferenceInstance::~PreferenceInstance() common::TizenResult PreferenceInstance::GetAll(const picojson::object& args, const common::AsyncToken& token) { ScopeLogger(); - // ... - return common::TizenSuccess(); + + return manager_.GetAll(SimplePost(token)); } common::TizenResult PreferenceInstance::SetValue(const picojson::object& args) { diff --git a/src/preference/preference_manager.cc b/src/preference/preference_manager.cc index a4d889dd..b9760040 100644 --- a/src/preference/preference_manager.cc +++ b/src/preference/preference_manager.cc @@ -15,6 +15,9 @@ */ #include + +#include + #include "common/logger.h" #include "common/tools.h" #include "preference/preference_manager.h" @@ -23,6 +26,8 @@ namespace extension { namespace preference { +std::mutex PreferenceManager::key_listener_mtx_; + namespace { const char* kKey = "key"; const char* kValue = "value"; @@ -78,8 +83,98 @@ int GetValueInternal(const std::string& key, picojson::value* val) { } return ret; } + +bool GetAllCb(const char* key, void* user_data) { + ScopeLogger(); + + if (!key) { + LoggerW("Key is null"); + return true; + } + + picojson::array* array = static_cast(user_data); + + if (!array) { + LoggerW("User data is null"); + return true; + } + + picojson::value val; + if (PREFERENCE_ERROR_NONE == GetValueInternal(key, &val)) { + picojson::value result_val{picojson::object{}}; + picojson::object& result_obj = result_val.get(); + + result_obj.insert(std::make_pair(kKey, picojson::value(key))); + result_obj.insert(std::make_pair(kValue, val)); + + array->push_back(result_val); + } + + return true; +} + +void ChangedCb(const char* key, void* user_data) { + ScopeLogger(); + + if (!key) { + LoggerW("Key is null"); + return; + } + + common::PostCallback* callback = static_cast(user_data); + if (!callback) { + LoggerW("User data is null"); + return; + } + + picojson::value val; + + if (PREFERENCE_ERROR_NONE == GetValueInternal(key, &val)) { + picojson::value result_val{picojson::object{}}; + picojson::object& result_obj = result_val.get(); + + result_obj.insert(std::make_pair(kKey, picojson::value(key))); + result_obj.insert(std::make_pair(kValue, val)); + + (*callback)(common::TizenSuccess(), result_val); + } else { + LoggerE("preference_set_ function error"); + } +} } // namespace +PreferenceManager::~PreferenceManager() { + ScopeLogger(); + + std::lock_guard lock(key_listener_mtx_); + for (const auto& it : key_listeners_) { + preference_unset_changed_cb(it.c_str()); + } +} + +common::TizenResult PreferenceManager::GetAll(const common::PostCallback& callback) { + ScopeLogger(); + + auto get_all = [](const common::PostCallback& callback) -> void { + picojson::value response{picojson::array{}}; + auto* array = &response.get(); + + int ret = preference_foreach_item(GetAllCb, array); + + common::TizenResult result = common::TizenSuccess(); + + if (PREFERENCE_ERROR_NONE != ret) { + result = MakeErrResult(ret, "preference_foreach_item function error"); + } + + callback(result, response); + }; + + std::thread(get_all, callback).detach(); + + return common::TizenSuccess(); +} + common::TizenResult PreferenceManager::SetValue(const std::string& key, const picojson::value& value) { ScopeLogger(); @@ -154,16 +249,24 @@ common::TizenResult PreferenceManager::Exists(const std::string& key) { } common::TizenResult PreferenceManager::SetChangeListener(const std::string& key, - common::PostCallback callback) { + const common::PostCallback callback) { ScopeLogger(); - if (!post_callback_) { - post_callback_ = callback; + if (!post_changed_callback_) { + post_changed_callback_ = callback; } - int ret = preference_set_changed_cb(key.c_str(), ChangedCb, (void*) this); + std::lock_guard lock(key_listener_mtx_); + for (const auto& it : key_listeners_) { + if (key == it) { + return common::TizenSuccess(); + } + } - if (ret == PREFERENCE_ERROR_NONE) { + int ret = preference_set_changed_cb(key.c_str(), ChangedCb, (void*) &post_changed_callback_); + + if (PREFERENCE_ERROR_NONE == ret) { + key_listeners_.push_back(key); return common::TizenSuccess(); } else { return MakeErrResult(ret, "preference_set_changed_cb function error"); @@ -173,39 +276,23 @@ common::TizenResult PreferenceManager::SetChangeListener(const std::string& key, common::TizenResult PreferenceManager::UnsetChangeListener(const std::string& key) { ScopeLogger(); - if (post_callback_) { - int ret = preference_unset_changed_cb(key.c_str()); - - if (ret == PREFERENCE_ERROR_NONE) { - return common::TizenSuccess(); - } else { - return MakeErrResult(ret, "preference_unset_changed_cb function error"); - } - } else { - return common::TizenSuccess(); - } -} - -void PreferenceManager::ChangedCb(const char* key, void* user_data) { - ScopeLogger(); - - PreferenceManager* manager = static_cast(user_data); + if (post_changed_callback_) { + std::lock_guard lock(key_listener_mtx_); + for (auto it = key_listeners_.begin(); it != key_listeners_.end(); ++it) { + if (key == (*it)) { + int ret = preference_unset_changed_cb(key.c_str()); - picojson::value result_val{picojson::object{}}; - picojson::object& result_obj = result_val.get(); - - result_obj.insert(std::make_pair(kKey, picojson::value(std::string(key)))); - - picojson::value val; + if (PREFERENCE_ERROR_NONE != ret) { + return MakeErrResult(ret, "preference_unset_changed_cb function error"); + } - if (GetValueInternal(key, &val) == PREFERENCE_ERROR_NONE) { - result_obj.insert(std::make_pair(kValue, val)); - if (manager->post_callback_) { - manager->post_callback_(common::TizenSuccess(), result_val); + key_listeners_.erase(it); + break; + } } - } else { - LoggerE("preference_set_ function error"); } + + return common::TizenSuccess(); } } // namespace preference diff --git a/src/preference/preference_manager.h b/src/preference/preference_manager.h index d68e230d..2f46539c 100644 --- a/src/preference/preference_manager.h +++ b/src/preference/preference_manager.h @@ -17,6 +17,8 @@ #ifndef PREFERENCE_PREFERENCE_MANAGER_H_ #define PREFERENCE_PREFERENCE_MANAGER_H_ +#include + #include "common/picojson.h" #include "common/tizen_instance.h" @@ -25,17 +27,20 @@ namespace preference { class PreferenceManager { public: + ~PreferenceManager(); + common::TizenResult GetAll(const common::PostCallback& callback); common::TizenResult SetValue(const std::string& key, const picojson::value& value); common::TizenResult GetValue(const std::string& key); common::TizenResult Remove(const std::string& key); common::TizenResult RemoveAll(void); common::TizenResult Exists(const std::string& key); - common::TizenResult SetChangeListener(const std::string& key, common::PostCallback callback); + common::TizenResult SetChangeListener(const std::string& key, const common::PostCallback callback); common::TizenResult UnsetChangeListener(const std::string& key); private: - static void ChangedCb(const char* key, void* user_data); - common::PostCallback post_callback_; + common::PostCallback post_changed_callback_; + std::vector key_listeners_; + static std::mutex key_listener_mtx_; }; } // namespace preference