[Features] Added fix for registered listeners.
[Verification] Code compiles.
Change-Id: I195900bb5495b609f47536d7069f5abdafdd1bd1
Signed-off-by: Andrzej Popowski <a.popowski@samsung.com>
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() {
}
};
-
PreferenceManager.prototype.getValue = function() {
var args = validator_.validateArgs(arguments, [
{ name: 'key', type: types_.STRING }
}
};
-
PreferenceManager.prototype.remove = function() {
var args = validator_.validateArgs(arguments, [
{ name: 'key', type: types_.STRING }
}
};
-
PreferenceManager.prototype.removeAll = function() {
var result = native_.callSync('PreferenceManager_removeAll', {});
}
};
-
PreferenceManager.prototype.exists = function() {
var args = validator_.validateArgs(arguments, [
{ name: 'key', type: types_.STRING }
}
};
+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);
};
}
+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, [
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 }
throw native_.getErrorObject(result);
}
- _preferenceListeners.removeListener(args.key);
+ _preferenceChangedListener.removeListener(args.key);
};
-
// Exports
exports = new PreferenceManager();
namespace {
const char* kKey = "key";
const char* kValue = "value";
+
const common::ListenerToken kPreferenceChangeListenerToken{"PREFERENCE_CHANGED"};
} // namespace
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) {
*/
#include <app_preference.h>
+
+#include <thread>
+
#include "common/logger.h"
#include "common/tools.h"
#include "preference/preference_manager.h"
namespace extension {
namespace preference {
+std::mutex PreferenceManager::key_listener_mtx_;
+
namespace {
const char* kKey = "key";
const char* kValue = "value";
}
return ret;
}
+
+bool GetAllCb(const char* key, void* user_data) {
+ ScopeLogger();
+
+ if (!key) {
+ LoggerW("Key is null");
+ return true;
+ }
+
+ picojson::array* array = static_cast<picojson::array*>(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<picojson::object>();
+
+ 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<common::PostCallback*>(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<picojson::object>();
+
+ 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<std::mutex> 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<picojson::array>();
+
+ 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();
}
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<std::mutex> 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");
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<PreferenceManager*>(user_data);
+ if (post_changed_callback_) {
+ std::lock_guard<std::mutex> 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<picojson::object>();
-
- 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
#ifndef PREFERENCE_PREFERENCE_MANAGER_H_
#define PREFERENCE_PREFERENCE_MANAGER_H_
+#include <mutex>
+
#include "common/picojson.h"
#include "common/tizen_instance.h"
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<std::string> key_listeners_;
+ static std::mutex key_listener_mtx_;
};
} // namespace preference