[Details] Replace set/unsetChangeListener with add/removeChangeListener.
[Verification] Code compiles and passes TCT content test suite.
Change-Id: I95d2d401586a031024894f760e113ae8ce885b5b
Signed-off-by: Mateusz Bruno-Kaminski <m.bruno2@samsung.com>
#include "content/content_manager.h"
#include "common/filesystem/filesystem_provider.h"
+using namespace common;
+
namespace extension {
namespace content {
ContentInstance::ContentInstance() :
noti_handle_(nullptr),
- listener_data_(nullptr) {
+ listener_handle_(nullptr),
+ listener_data_(nullptr),
+ callback_data_(nullptr) {
using std::placeholders::_1;
using std::placeholders::_2;
REGISTER_SYNC("ContentManager_scanFile", ContentManagerScanfile);
REGISTER_SYNC("ContentManager_scanDirectory", ContentManagerScanDirectory);
REGISTER_SYNC("ContentManager_cancelScanDirectory", ContentManagerCancelScanDirectory);
+ REGISTER_SYNC("ContentManager_addChangeListener", ContentManagerAddChangeListener);
+ REGISTER_SYNC("ContentManager_removeChangeListener", ContentManagerRemoveChangeListener);
REGISTER_SYNC("ContentManager_unsetChangeListener", ContentManagerUnsetchangelistener);
REGISTER_SYNC("ContentManager_setChangeListener", ContentManagerSetchangelistener);
REGISTER_SYNC("ContentManager_getDirectories", ContentManagerGetdirectories);
ContentInstance::~ContentInstance() {
LoggerD("entered");
+
if (noti_handle_) {
media_content_remove_db_updated_cb(noti_handle_);
noti_handle_ = nullptr;
}
+
+ if (listener_handle_) {
+ media_content_remove_db_updated_cb(listener_handle_);
+ listener_handle_ = nullptr;
+ }
+
if (listener_data_) {
delete listener_data_;
listener_data_ = nullptr;
}
+
+ if (callback_data_) {
+ delete callback_data_;
+ callback_data_ = nullptr;
+ }
+
ContentManager::getInstance()->setContentInstance(nullptr);
}
common::Instance::PostMessage(cbData->instance, picojson::value(out).serialize().c_str());
}
-
-static void changedContentCallback(media_content_error_e error,
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
+static void changedContentV1Callback(media_content_error_e error,
int pid,
media_content_db_update_item_type_e update_item,
media_content_db_update_type_e update_type,
}
}
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
static void changedContentV2Callback(media_content_error_e error,
int pid,
media_content_db_update_item_type_e update_item,
}
}
+static PlatformResult prepareDirectoryChangeResponse(media_content_db_update_type_e update_type,
+ char* uuid,
+ picojson::object& obj) {
+ LoggerD("Media item is a directory");
+
+ if (MEDIA_CONTENT_DELETE == update_type) {
+ ReportSuccess(picojson::value(std::string(uuid)), obj);
+ obj["state"] = picojson::value("oncontentdirremoved");
+ return PlatformResult(ErrorCode::NO_ERROR);
+ }
+
+ media_folder_h folder = nullptr;
+ int ret = media_folder_get_folder_from_db(uuid, &folder);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == folder) {
+ LoggerE("Failed to get media item (media_folder_get_folder_from_db): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ picojson::object o;
+ ContentDirToJson(folder, o);
+
+ ret = media_folder_destroy(folder);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
+ LoggerE("Failed to destroy media folder (media_folder_destroy): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ ReportSuccess(picojson::value(o), obj);
+
+ if (MEDIA_CONTENT_INSERT == update_type) {
+ obj["state"] = picojson::value("oncontentdiradded");
+ } else if (MEDIA_CONTENT_UPDATE == update_type) {
+ obj["state"] = picojson::value("oncontentdirupdated");
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult prepareFileChangeResponse(media_content_db_update_type_e update_type,
+ char* uuid,
+ picojson::object& obj) {
+ LoggerD("Media item is a file");
+
+ if (MEDIA_CONTENT_DELETE == update_type) {
+ ReportSuccess(picojson::value(std::string(uuid)), obj);
+ obj["state"] = picojson::value("oncontentremoved");
+ return PlatformResult(ErrorCode::NO_ERROR);
+ }
+
+ media_info_h media = nullptr;
+ int ret = media_info_get_media_from_db(uuid, &media);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media) {
+ LoggerE("Failed to get media item (media_info_get_media_from_db): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ picojson::object o;
+ ContentToJson(media, o);
+
+ ret = media_info_destroy(media);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
+ LoggerE("Failed to destroy media info (media_info_destroy): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ ReportSuccess(picojson::value(o), obj);
+
+ if (MEDIA_CONTENT_INSERT == update_type) {
+ obj["state"] = picojson::value("oncontentadded");
+ } else if (MEDIA_CONTENT_UPDATE == update_type) {
+ obj["state"] = picojson::value("oncontentupdated");
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void contentChangeCallback(media_content_error_e error,
+ int pid,
+ media_content_db_update_item_type_e update_item,
+ media_content_db_update_type_e update_type,
+ media_content_type_e media_type,
+ char* uuid,
+ char* path,
+ char* mime_type,
+ void* user_data) {
+ LoggerD("Entered directory and file change callback");
+
+ if (MEDIA_CONTENT_ERROR_NONE != error) {
+ LoggerE("Failed to perform contentChangeCallback: %d", error);
+ return;
+ }
+
+ if (!uuid) {
+ LoggerE("Provided uuid is NULL, ignoring");
+ return;
+ }
+
+ if (nullptr == user_data) {
+ LoggerE("Provided user data is NULL, ignoring");
+ return;
+ }
+
+ if (MEDIA_ITEM_DIRECTORY != update_item && MEDIA_ITEM_FILE != update_item) {
+ LoggerD("Media item is not a directory nor a file, skipping");
+ return;
+ }
+
+ ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+
+ picojson::value result = picojson::value(picojson::object());
+ picojson::object& obj = result.get<picojson::object>();
+
+ PlatformResult ret(ErrorCode::NO_ERROR);
+ if (MEDIA_ITEM_DIRECTORY == update_item) {
+ ret = prepareDirectoryChangeResponse(update_type, uuid, obj);
+ } else if (MEDIA_ITEM_FILE == update_item) {
+ ret = prepareFileChangeResponse(update_type, uuid, obj);
+ }
+
+ if (ret.IsSuccess()) {
+ obj["listenerId"] = picojson::value("ContentManagerChangeCallback");
+ Instance::PostMessage(cbData->instance, result.serialize().c_str());
+ } else {
+ LoggerD("Failed to prepare content change callback, ignoring");
+ }
+}
+
#define CHECK_EXIST(args, name, out) \
if (!args.contains(name)) {\
LogAndReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, (name" is required argument")), &out);\
}
}
+void ContentInstance::ContentManagerAddChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Entered");
+
+ callback_data_ = new ReplyCallbackData();
+ callback_data_->instance = this;
+ callback_data_->args = args;
+
+ if (ContentManager::getInstance()->isConnected()) {
+ callback_data_->cbType = ContentManagerAddChangeListenerCallback;
+ } else {
+ callback_data_->cbType = ContentManagerErrorCallback;
+ }
+
+ PlatformResult result =
+ ContentManager::getInstance()->addChangeListener(&listener_handle_,
+ contentChangeCallback,
+ static_cast<void*>(callback_data_));
+
+ if (result.IsError()) {
+ delete callback_data_;
+ callback_data_ = nullptr;
+ LogAndReportError(result, &out);
+ }
+}
+
+void ContentInstance::ContentManagerRemoveChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Entered");
+
+ PlatformResult result = ContentManager::getInstance()->removeChangeListener(listener_handle_);
+
+ if (result.IsSuccess()) {
+ listener_handle_ = nullptr;
+ delete callback_data_;
+ callback_data_ = nullptr;
+ } else {
+ LogAndReportError(result, &out);
+ }
+}
void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
picojson::object& out) {
LoggerD("entered");
+ LoggerW("DEPRECATION WARNING: setChangeListener() is deprecated and will be removed from next release. "
+ "Use addChangeListener() instead.");
//CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
listener_data_->cbType = ContentManagerErrorCallback;
}
- if (ContentManager::getInstance()->setChangeListener(changedContentCallback,
+ if (ContentManager::getInstance()->setChangeListener(changedContentV1Callback,
static_cast<void*>(listener_data_)).IsError()) {
LogAndReportError(
common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
}
- if (ContentManager::getInstance()->setV2ChangeListener(¬i_handle_,
- changedContentV2Callback,
- static_cast<void*>(listener_data_)).IsError()) {
- LogAndReportError(
- common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+
+ if (nullptr == noti_handle_) { // To remain consistency with the previous implementation
+ if (ContentManager::getInstance()->addChangeListener(¬i_handle_,
+ changedContentV2Callback,
+ static_cast<void*>(listener_data_)).IsError()) {
+ LogAndReportError(
+ common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+ }
}
}
void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out) {
LoggerD("entered");
+ LoggerW("DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed from next release. "
+ "Use removeChangeListener() instead.");
//CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
if (ContentManager::getInstance()->unSetChangeListener().IsError()) {
LoggerD("unsuccesfull deregistering of callback");
}
- if (ContentManager::getInstance()->unSetV2ChangeListener(¬i_handle_).IsError()) {
+ if (ContentManager::getInstance()->removeChangeListener(noti_handle_).IsError()) {
LoggerD("unsuccesfull deregistering of callback");
+ } else {
+ noti_handle_ = nullptr; // To remain consistency with the previous implementation
}
}
#ifndef CONTENT_CONTENT_INSTANCE_H_
#define CONTENT_CONTENT_INSTANCE_H_
+#include <map>
+
#include <media_content_internal.h>
#include "common/extension.h"
enum ContentCallbacks {
ContentManagerFindCallback,
ContentManagerScanfileCallback,
+ ContentManagerAddChangeListenerCallback,
+ ContentManagerRemoveChangeListenerCallback,
ContentManagerUnsetchangelistenerCallback,
ContentManagerSetchangelistenerCallback,
ContentManagerGetdirectoriesCallback,
void ContentManagerScanfile(const picojson::value& args, picojson::object& out);
void ContentManagerScanDirectory(const picojson::value& args, picojson::object& out);
void ContentManagerCancelScanDirectory(const picojson::value& args, picojson::object& out);
+ void ContentManagerAddChangeListener(const picojson::value& args, picojson::object& out);
+ void ContentManagerRemoveChangeListener(const picojson::value& args, picojson::object& out);
void ContentManagerSetchangelistener(const picojson::value& args, picojson::object& out);
void ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out);
void ContentManagerGetplaylists(const picojson::value& args, picojson::object& out);
void PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out);
void PlaylistGetNumberOfTracks(const picojson::value& args, picojson::object& out);
- media_content_noti_h noti_handle_;
- ReplyCallbackData* listener_data_;
+ media_content_noti_h noti_handle_; // Deprecated handle
+ media_content_noti_h listener_handle_;
+
+ ReplyCallbackData* listener_data_; // Deprecated callback data
+ ReplyCallbackData* callback_data_;
};
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
+PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
+ media_content_db_update_cb callback,
void *user_data) {
LoggerD("Enter");
- int ret = media_content_set_db_updated_cb(callback, user_data);
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
+ int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
- ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
+ ErrorCode::ABORT_ERR,
+ "Failed to add the listener.",
+ ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
}
+
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::unSetChangeListener() {
+PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
LoggerD("Enter");
- int ret = media_content_unset_db_updated_cb();
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
- return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
- ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
+ int ret = media_content_remove_db_updated_cb(noti_handle);
+
+ switch (ret) {
+ case MEDIA_CONTENT_ERROR_NONE:
+ return PlatformResult(ErrorCode::NO_ERROR);
+ case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
+ // Trying to remove non-existent listener, ignoring
+ LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
+ return PlatformResult(ErrorCode::NO_ERROR);
+ default:
+ return LogAndCreateResult(
+ ErrorCode::ABORT_ERR,
+ "Failed to remove the listener.",
+ ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
}
- return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::setV2ChangeListener(media_content_noti_h* noti_handle,
- media_content_db_update_cb callback,
+PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
void *user_data) {
LoggerD("Enter");
- if (nullptr == *noti_handle) {
- int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
- return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
- ("Failed: registering the listener of cb_v2 is failed: %d (%s)",
- ret, get_error_message(ret)));
- }
+
+ int ret = media_content_set_db_updated_cb(callback, user_data);
+ if(ret != MEDIA_CONTENT_ERROR_NONE) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
+ ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
}
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::unSetV2ChangeListener(media_content_noti_h* noti_handle) {
+PlatformResult ContentManager::unSetChangeListener() {
LoggerD("Enter");
- int ret = media_content_remove_db_updated_cb(*noti_handle);
+ int ret = media_content_unset_db_updated_cb();
if(ret != MEDIA_CONTENT_ERROR_NONE) {
return LogAndCreateResult(
ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
- ("Failed: unregistering the listener of cb_v2 is failed %d (%s)",
- ret, get_error_message(ret)));
+ ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
}
- *noti_handle = nullptr;
-
return PlatformResult(ErrorCode::NO_ERROR);
}
-
void ContentManager::createPlaylist(std::string name,
const std::shared_ptr<ReplyCallbackData>& user_data) {
LoggerD("Enter");
int scanFile(std::string& uri);
common::PlatformResult scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData);
common::PlatformResult cancelScanDirectory(const std::string& content_dir_uri);
+ common::PlatformResult addChangeListener(media_content_noti_h* noti_handle,
+ media_content_db_update_cb callback,
+ void *user_data);
+ common::PlatformResult removeChangeListener(media_content_noti_h noti_handle);
common::PlatformResult setChangeListener(media_content_db_update_cb callback,
void *user_data);
common::PlatformResult unSetChangeListener();
- common::PlatformResult setV2ChangeListener(media_content_noti_h* noti_handler,
- media_content_db_update_cb callback,
- void *user_data);
- common::PlatformResult unSetV2ChangeListener(media_content_noti_h* noti_handler);
//Lyrics
int getLyrics(const picojson::value& args,picojson::object& result);
* limitations under the License.
*/
+var T_ = xwalk.utils.type;
+var CONTENT_MANAGER_LISTENER_ID = 'ContentManagerChangeCallback';
+
+
function _ContentManagerChangeCallback(result) {
if (result.state === 'oncontentadded' || result.state === 'oncontentupdated') {
var content = native_.getResultObject(result);
}
}
+
+var ContentListenersManager = (function() {
+
+ function changeContent(event) {
+ if (T_.isEmptyObject(this.listeners)) {
+ return;
+ }
+
+ var result = null;
+
+ if (event.state === 'oncontentadded' || event.state === 'oncontentupdated') {
+ result = createContentObject_(native_.getResultObject(event));
+ } else if (event.state === 'oncontentdiradded' || event.state === 'oncontentdirupdated') {
+ result = createContentDirObject_(native_.getResultObject(event));
+ } else if (event.state === 'oncontentremoved' || event.state === 'oncontentdirremoved') {
+ result = native_.getResultObject(event);
+ }
+
+ if (!result) {
+ return;
+ }
+
+ var callback;
+ for (var listenerId in this.listeners) {
+ if (this.listeners.hasOwnProperty(listenerId)) {
+ callback = this.listeners[listenerId];
+ if (T_.isFunction(callback[event.state])) {
+ callback[event.state](result);
+ }
+ }
+ }
+ }
+
+ function _ContentListenersManager() {
+ this.listeners = {};
+ this.lastListenerId = 0;
+ this.changeContent = changeContent.bind(this);
+ }
+
+ _ContentListenersManager.prototype.addChangeListener = function(changeCallback) {
+ if (T_.isEmptyObject(this.listeners)) {
+ var result = native_.callSync('ContentManager_addChangeListener');
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+
+ native_.addListener(CONTENT_MANAGER_LISTENER_ID, this.changeContent);
+ }
+
+ this.listeners[++this.lastListenerId] = changeCallback;
+ return this.lastListenerId;
+ };
+
+ _ContentListenersManager.prototype.removeChangeListener = function(listenerId) {
+ delete this.listeners[listenerId];
+
+ if (T_.isEmptyObject(this.listeners)) {
+ var result = native_.callSync('ContentManager_removeChangeListener');
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+
+ native_.removeListener(CONTENT_MANAGER_LISTENER_ID);
+ }
+ };
+
+ return _ContentListenersManager;
+})();
+
+var listenersManager = new ContentListenersManager();
+
+
function ContentManager() {
}
}
};
+ContentManager.prototype.addChangeListener = function() {
+ var args = validator_.validateArgs(arguments, [{
+ name: 'changeCallback',
+ type: types_.LISTENER,
+ values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
+ }]);
+
+ return listenersManager.addChangeListener(args.changeCallback);
+};
+
+ContentManager.prototype.removeChangeListener = function() {
+ var args = validator_.validateArgs(arguments, [{
+ name: 'listenerId',
+ type: types_.LONG
+ }]);
+
+ listenersManager.removeChangeListener(args.listenerId);
+};
+
ContentManager.prototype.setChangeListener = function(changeCallback) {
+ console.warn('DEPRECATION WARNING: setChangeListener() is deprecated and will be removed '
+ + 'from next release. Use addChangeListener() instead.');
+
var args = validator_.validateArgs(arguments, [{
name: 'changeCallback',
type: types_.LISTENER,
values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
}]);
- var listenerId = 'ContentManagerChangeCallback';
+ var listenerId = 'ContentManagerChangeCallback_';
var data = {
listenerId: listenerId
oncontentdirremoved: args.changeCallback.oncontentdirremoved
};
- native_.addListener('ContentManagerChangeCallback',
- _ContentManagerChangeCallback.bind(callbacks));
-
var result = native_.callSync('ContentManager_setChangeListener', data);
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
+
+ native_.addListener('ContentManagerChangeCallback_',
+ _ContentManagerChangeCallback.bind(callbacks));
};
ContentManager.prototype.unsetChangeListener = function() {
+ console.warn('DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed '
+ + 'from next release. Use removeChangeListener() instead.');
+
var data = {};
var result = native_.callSync('ContentManager_unsetChangeListener', data);
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
+
+ native_.removeListener('ContentManagerChangeCallback_');
};
ContentManager.prototype.getPlaylists = function(successCallback, errorCallback) {