[Preference] - getAll function implemented
authorAndrzej Popowski <a.popowski@samsung.com>
Mon, 4 Apr 2016 13:11:23 +0000 (15:11 +0200)
committerTomasz Marciniak <t.marciniak@samsung.com>
Fri, 15 Apr 2016 12:57:03 +0000 (14:57 +0200)
[Features] Added fix for registered listeners.

[Verification] Code compiles.

Change-Id: I195900bb5495b609f47536d7069f5abdafdd1bd1
Signed-off-by: Andrzej Popowski <a.popowski@samsung.com>
src/preference/preference_api.js
src/preference/preference_instance.cc
src/preference/preference_manager.cc
src/preference/preference_manager.h

index 9ddd75e9b1a3b6a56fec0389be669a0b95689c63..23434021cf569dd1d3d3f35fad817286885a4eea 100644 (file)
@@ -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();
 
index 1b6d2c522e33654f67b0309dc18554175c3e8ee7..851689bade3a66258fadd4e0e466928a42c962c6 100644 (file)
@@ -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) {
index a4d889ddf47bc3bcab233f0c53f81d7d0967ccad..b97600409479f63a9e347885fc1884a6e2d9dd9f 100644 (file)
@@ -15,6 +15,9 @@
  */
 
 #include <app_preference.h>
+
+#include <thread>
+
 #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<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();
 
@@ -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<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");
@@ -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<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
index d68e230d16a44af4cd72f1afde8412a76dd9cf82..2f46539c2e265a4568a0fe9a3579d53a06067860 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef PREFERENCE_PREFERENCE_MANAGER_H_
 #define PREFERENCE_PREFERENCE_MANAGER_H_
 
+#include <mutex>
+
 #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<std::string> key_listeners_;
+  static std::mutex key_listener_mtx_;
 };
 
 } // namespace preference