[content] js refactoring
authorRafal Galka <r.galka@samsung.com>
Thu, 19 Mar 2015 13:58:55 +0000 (14:58 +0100)
committerRafal Galka <r.galka@samsung.com>
Fri, 20 Mar 2015 14:33:09 +0000 (23:33 +0900)
[Verification]
TCT 2.4 result: 85/230

Change-Id: I34f146a4a2c112512e18af85685c06fe127b490a

src/content/content_api.js
src/content/content_extension.cc
src/content/content_extension.h
src/content/content_instance.cc
src/content/content_instance.h
src/content/content_manager.cc
src/content/js/common.js [new file with mode: 0644]
src/content/js/datatypes.js [new file with mode: 0644]
src/content/js/manager.js [new file with mode: 0644]
src/content/js/playlist.js [new file with mode: 0644]

index 45d18aab95c2af702ce9e9282b440ada4eca805b..844cb7f1b1979d347af2bbe075da22ac9c272b44 100755 (executable)
-// Content
+/* global tizen, xwalk, extension */
 
-var utils_ = xwalk.utils;
-var validator_ = utils_.validator;
-var types_ = validator_.Types;
-
-
-var callbackId = 0;
-var callbacks = {};
-
-extension.setMessageListener(function(json) {
-  var result = JSON.parse(json);
-  var callback = callbacks[result['callbackId']];
-  callback(result);
-});
-
-function nextCallbackId() {
-  return callbackId++;
-}
-
-
-var ExceptionMap = {
-  'UnknownError' : WebAPIException.UNKNOWN_ERR ,
-  'TypeMismatchError' : WebAPIException.TYPE_MISMATCH_ERR ,
-  'InvalidValuesError' : WebAPIException.INVALID_VALUES_ERR ,
-  'IOError' : WebAPIException.IO_ERR ,
-  'ServiceNotAvailableError' : WebAPIException.SERVICE_NOT_AVAILABLE_ERR ,
-  'SecurityError' : WebAPIException.SECURITY_ERR ,
-  'NetworkError' : WebAPIException.NETWORK_ERR ,
-  'NotSupportedError' : WebAPIException.NOT_SUPPORTED_ERR ,
-  'NotFoundError' : WebAPIException.NOT_FOUND_ERR ,
-  'InvalidAccessError' : WebAPIException.INVALID_ACCESS_ERR ,
-  'AbortError' : WebAPIException.ABORT_ERR ,
-  'QuotaExceededError' : WebAPIException.QUOTA_EXCEEDED_ERR ,
-}
-
-function callNative(cmd, args) {
-  var json = {'cmd':cmd, 'args':args};
-  var argjson = JSON.stringify(json);
-  var resultString = extension.internal.sendSyncMessage(argjson)
-  var result = JSON.parse(resultString);
-
-  if (typeof result !== 'object') {
-    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
-  }
-
-  if (result['status'] == 'success') {
-    if(result['result']) {
-        return result['result'];
-    }
-    return true;
-  } else if (result['status'] == 'error') {
-    var err = result['error'];
-    if(err) {
-        if(ExceptionMap[err.name]) {
-            throw new WebAPIException(ExceptionMap[err.name], err.message);
-        } else {
-            throw new WebAPIException(WebAPIException.UNKNOWN_ERR, err.message);
-        }
-    }
-    return false;
-  }
-}
-
-
-function callNativeWithCallback(cmd, args, callback) {
-  if(callback) {
-    var id = nextCallbackId();
-    args['callbackId'] = id;
-    callbacks[id] = callback;
-  }
-  return callNative(cmd, args);
-}
-
-function SetReadOnlyProperty(obj, n, v){
-  Object.defineProperty(obj, n, {value:v, writable: false});
-}
-
-function Playlist(id, name, numberOfTracks, thumbnailURI) {
-  var name_ = name;
-  Object.defineProperties(this, {
-    'id': { writable: false, value: id, enumerable: true },
-    'name': { writable: true, value: name, enumerable: true },
-    'numberOfTracks': { writable: false, value: numberOfTracks, enumerable: true },
-    'thumbnailURI': {writable: true, value: thumbnailURI, enumerable: true }
-  });
-}
-
-function PlaylistItem(content,playlist_member_id) {
-  var content_ = content;
-  var member_id = playlist_member_id;
-  Object.defineProperties(this, {
-    'content': { writable: false, value: content, enumerable: true },
-    'member_id': {enumerable: false,
-      set: function(v) { if (v != null) member_id = v},
-      get: function() { return member_id; }
-    }
-  });
-}
-
-
-Playlist.prototype.add = function(item) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'item', 'type': types_.PLATFORM_OBJECT, 'values': Content, 'optional' : false, 'nullable' : false}
-  ]);
-  var nativeParam = {
-    'playlist_id': this.id
-  };
-
-  if (args['item']) {
-    nativeParam['content_id'] = args.item.id;
-  }
-  try {
-    var syncResult = callNative('ContentPlaylist_add', nativeParam);
-  } catch(e) {
-    throw e;
-  }
-}
-
-Playlist.prototype.remove = function(item) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'item', 'type': types_.PLATFORM_OBJECT, 'values': PlaylistItem, 'optional' : false, 'nullable' : false}
-  ]);
-  var nativeParam = {
-    'playlist_id': this.id,
-    'member_id' : args.item.member_id
-  };
-
-  try {
-    var syncResult = callNative('ContentPlaylist_remove', nativeParam);
-  } catch(e) {
-    throw e;
-  }
-}
-
-
-Playlist.prototype.removeBatch = function(items) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'items', 'type': types_.ARRAY},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'playlist_id': this.id,
-  };
-
-  nativeParam["members"] = [];
-  if (args['items']) {
-    for (var i = 0; i < args.items.length; i++) {
-      var c = args.items[i];
-      nativeParam.members.push(c.member_id);
-    }
-  }
-
-  try {
-    var syncResult = callNativeWithCallback('ContentPlaylist_removeBatch', nativeParam, function(result) {
-      if (result.status == 'success') {
-        args.successCallback();
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-}
-
-
-Playlist.prototype.get = function() {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'successCallback', 'type': types_.FUNCTION},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'count', 'type': types_.LONG, optional : true, nullable : true},
-    {'name' : 'offset', 'type': types_.LONG, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'playlist_id': this.id
-  };
-
-  if (args['count']) {
-    nativeParam['count'] = args.count;
-  }
-  else {
-    nativeParam['count'] = -1;
-  }
-  if (args['offset']) {
-    nativeParam['offset'] = args.offset;
-  }
-  else {
-    nativeParam['offset'] = -1;
-  }
-
-  try {
-    var syncResult = callNativeWithCallback('ContentPlaylist_get', nativeParam, function(result) {
-      if (result.status == 'success') {
-        var items = [];
-        for (var i = 0; i < result.value.length; i++) {
-          var c = result.value[i];
-          var content = createContent(c);
-          var item = new PlaylistItem(content,c.playlist_member_id);
-          items.push(item);
-        }
-        args.successCallback(items);
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  }
-  catch(e) {
-    throw e;
-  }
-}
-
-Playlist.prototype.addBatch = function() {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'items', 'type': types_.ARRAY},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'playlist_id': this.id,
-    'contents' : args.items
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentPlaylist_addBatch', nativeParam, function(result) {
-      if (result.status == 'success') {
-        args.successCallback();
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-      throw e;
-  }
-}
-
-
-Playlist.prototype.setOrder  = function() {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'items', 'type': types_.ARRAY},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'playlist_id': this.id,
-  };
-
-  nativeParam["members"] = [];
-  if (args['items']) {
-    for (var i = 0; i < args.items.length; i++) {
-      var c = args.items[i];
-      nativeParam.members.push(c.member_id);
-    }
-  }
-
-  try {
-    var syncResult = callNativeWithCallback('ContentPlaylist_setOrder', nativeParam, function(result) {
-      if (result.status == 'success') {
-        args.successCallback();
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-}
-
-Playlist.prototype.move  = function(item, delta) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'item', 'type': types_.PLATFORM_OBJECT, 'values': PlaylistItem},
-    {'name' : 'delta', 'type': types_.LONG},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'playlist_id': this.id,
-    'member_id': args.item.member_id,
-    'delta' : args.delta
-  };
-
-  try {
-
-    var syncResult = callNativeWithCallback('ContentPlaylist_move', nativeParam, function(result) {
-      if (result.status == 'success') {
-          args.successCallback();
-      }
-      else if(result.status == 'error') {
-          var err = result['value'];
-          args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-}
-
-
-function ContentDirectory(id, uri, type, title, date) {
-  Object.defineProperties(this, {
-    'id': { writable: false, value: id, enumerable: true },
-    'directoryURI': { writable: false, value: uri, enumerable: true },
-    'title': { writable: false, value: title, enumerable: true },
-    'storageType': { writable: false, value: type, enumerable: true },
-    'date': { writable: false, value: date, enumerable: true },
-  });
-}
-
-
-function Content(id, name,type, mimeType, title, contentURI, thumbnailURIs,
-  releaseDate, modifiedDate, size, description, rating, isFavorite) {
-  var name_ = name;
-  var rating_ = rating;
-  var editableAttributes_= ["name", "description", "rating", "isFavorite"];
-
-  if (type === "IMAGE") {
-    editableAttributes_.push("geolocation");
-    editableAttributes_.push("orientation");
-  }
-  else if(type === "VIDEO") {
-    editableAttributes_.push("geolocation");
-  }
-  Object.defineProperties(this, {
-    'editableAttributes':
-      { enumerable: true,
-        get: function() { return editableAttributes_; }
-      },
-    'id':
-      { writable: false, value: id, enumerable: true },
-    'name':
-      { enumerable: true,
-        set: function(v) { if (v != null) name_ = v},
-        get: function() { return name_; }
-      },
-    'type':
-      { writable: false, value: type, enumerable: true },
-    'mimeType':
-      { writable: false, value: mimeType, enumerable: true },
-    'title':
-      { writable: false, value: title, enumerable: true },
-    'contentURI':
-      { writable: false, value: contentURI, enumerable: true },
-    'thumbnailURIs':
-      { writable: false, value: thumbnailURIs, enumerable: true },
-    'releaseDate':
-      { writable: false, value: releaseDate, enumerable: true },
-    'modifiedDate':
-      { writable: false, value: modifiedDate, enumerable: true },
-    'size':
-      { writable: false, value: size, enumerable: true },
-    'description':
-      { writable: true, value: description, enumerable: true },
-    'rating':
-      { enumerable: true,
-        set: function(v) { if (v != null && v >= 0 && v <= 10) rating_ = v; },
-        get: function() { return rating_; }
-      },
-    'isFavorite':
-      { writable: true, value: isFavorite, enumerable: true }
-  });
-}
-
-function ImageContent(obj, width, height, orientation, geolocation) {
-  Object.defineProperties(obj, {
-    'width':
-      { writable: false, value: width, enumerable: true },
-    'height':
-      { writable: false, value: height, enumerable: true },
-    'orientation':
-      { writable: true, value: orientation, enumerable: true },
-    'geolocation':
-      { writable: true, value: geolocation, enumerable: true }
-  });
-}
-
-function VideoContent(obj, geolocation, album, artists, duration, width, height) {
-  Object.defineProperties(obj, {
-    'geolocation':
-      { writable: true, value: geolocation, enumerable: true },
-    'album':
-      { writable: false, value: album, enumerable: true },
-    'artists':
-      { writable: false, value: artists, enumerable: true },
-    'duration':
-      { writable: false, value: duration, enumerable: true },
-    'width':
-      { writable: false, value: width, enumerable: true },
-    'height':
-      { writable: false, value: height, enumerable: true }
-  });
-}
-
-function AudioContentLyrics(type, timestamps, texts) {
-  Object.defineProperties(this, {
-    'type':
-      { writable: false, value: type, enumerable: true },
-    'timestamps':
-      { writable: false, value: timestamps, enumerable: true },
-    'texts':
-      { writable: false, value: texts, enumerable: true }
-  });
-}
-
-function AudioContent(obj, album, genres, artists, composers, copyright,
-  bitrate, trackNumber, duration) {
-  var lyrics_ = null;
-  function getLyrics(contentURI) {
-    var nativeParam = {
-      'contentURI': contentURI
-    };
-
-    var syncResult = callNative('ContentManager_getLyrics', nativeParam);
-
-    if (syncResult.status == 'success') {
-      var l = syncResult['result'];
-      lyrics_ = new AudioContentLyrics(l.type, l.timestamps, l.texts);
-    }
-    else {
-      console.log("Getting the lyrics is failed.");
-    }
-  }
-  Object.defineProperties(obj, {
-    'album':
-      { writable: false, value: album, enumerable: true },
-    'genres':
-      { writable: false, value: genres, enumerable: true },
-    'artists':
-      { writable: false, value: artists, enumerable: true },
-    'composers':
-      { writable: false, value: composers, enumerable: true },
-    'copyright':
-      { writable: false, value: copyright, enumerable: true },
-    'bitrate':
-      { writable: false, value: bitrate, enumerable: true },
-    'trackNumber':
-      { writable: false, value: trackNumber, enumerable: true },
-    'duration':
-      { writable: false, value: duration, enumerable: true },
-    'lyrics':
-      { enumerable: true,
-        get: function() {
-               if(lyrics_ === undefined) {
-                       getLyrics(obj.contentURI);
-               }
-          else if(lyrics_ === null) {
-            lyrics_ = undefined;
-          }
-               return lyrics_;
-        }
-      }
-  });
-}
-
-function createContent(c) {
-  var content = new Content(c.id,
-    c.name,
-    c.type,
-    c.mimeType,
-    c.title,
-    c.contentURI,
-    c.thumbnailURIs,
-    c.releaseDate,
-    c.modifiedDate,
-    c.size,
-    c.description,
-    c.rating,
-    c.isFavorite
-  );
-  if (c.type === "IMAGE") {
-    var image = new ImageContent(content,
-      c.width,
-      c.height,
-      c.orientation,
-      c.geolocation
-    );
-  }
-  else if (c.type === "VIDEO") {
-    var video = new VideoContent(content,
-      c.geolocation,
-      c.album,
-      c.artists,
-      c.duration,
-      c.width,
-      c.height
-    );
-  }
-  else if(c.type === "AUDIO") {
-    var audio = new AudioContent(content,
-      c.album,
-      c.genres,
-      c.artists,
-      c.composers,
-      c.copyright,
-      c.bitrate,
-      c.trackNumber,
-      c.duration
-    );
-  }
-  return content;
-}
-
-
-function ContentManager() {
-    // constructor of ContentManager
-}
-
-//void update (Content content)
-ContentManager.prototype.update = function(content) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'content', 'type': types_.PLATFORM_OBJECT, 'values': Content}
-  ]);
-  var nativeParam = {};
-  if (args['content']) {
-      nativeParam['content'] = args.content;
-  }
-  try {
-    var syncResult = callNative('ContentManager_update', nativeParam);
-  } catch(e) {
-    throw e;
-  }
-}
-
-ContentManager.prototype.updateBatch = function(contents) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'contents', 'type': types_.ARRAY},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'contents' : args.contents
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_updateBatch', nativeParam, function(result) {
-      if (result.status == 'success') {
-        args.successCallback();
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-      throw e;
-  }
-}
-
-ContentManager.prototype.getDirectories = function(successCallback) {
-  var args = validator_.validateArgs(arguments, [
-      {'name' : 'successCallback', 'type': types_.FUNCTION, optional : false, nullable : false},
-      {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_getDirectories', nativeParam, function(result) {
-      if (result.status == 'success') {
-        var dirs = [];
-
-        for (var i = 0; i < result.value.length; i++) {
-          var res = result.value[i];
-          var dir = new ContentDirectory(
-            res.id,
-            res.directoryURI,
-            res.title,
-            res.storageType,
-            res.modifiedDate
-          );
-
-          dirs.push(dir);
-        }
-        args.successCallback(dirs);
-      }
-      else if(result.status == 'error') {
-          var err = result['value'];
-          args.errorCallback(err);
-      }
-    });
-      // if you need synchronous result from native function using 'syncResult'.
-  }
-  catch(e) {
-    throw e;
-  }
-}
-
-ContentManager.prototype.find = function(successCallback) {
-  var args = validator_.validateArgs(arguments, [
-      {'name' : 'successCallback', 'type': types_.FUNCTION, 'values' : ['onsuccess']},
-      {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-      {'name' : 'directoryId', 'type': types_.STRING, optional : true, nullable : true},
-      {'name' : 'filter', 'type': types_.PLATFORM_OBJECT,
-        values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
-        optional : true, nullable : true },
-      {'name' : 'sortMode', 'type': types_.DICTIONARY, optional : true, nullable : true},
-      {'name' : 'count', 'type': types_.UNSIGNED_LONG, optional : true},
-      {'name' : 'offset', 'type': types_.UNSIGNED_LONG, optional : true}
-  ]);
-  if (args.offset < 0 || args.count < 0) {
-    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var nativeParam = {
-  };
-
-  if (args['directoryId']) {
-      nativeParam['directoryId'] = args.directoryId;
-  }
-  if (args['filter']) {
-      nativeParam['filter'] = utils_.repackFilter(args.filter);
-  }
-  if (args['sortMode']) {
-      nativeParam['sortMode'] = args.sortMode;
-  }
-  if (args['count']) {
-      nativeParam['count'] = args.count;
-  }
-  if (args['offset']) {
-      nativeParam['offset'] = args.offset;
-  }
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_find', nativeParam, function(result) {
-      if (result.status == 'success') {
-        var contents = [];
-        for ( var i = 0; i < result.value.length; i++) {
-          var c = result.value[i];
-
-          var content = createContent(c);
-
-          contents.push(content);
-        }
-        args.successCallback(contents);
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-      // if you need synchronous result from native function using 'syncResult'.
-  } catch(e) {
-    throw e;
-  }
-
-}
-
-ContentManager.prototype.scanFile = function(contentURI) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'contentURI', 'type': types_.STRING},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'contentURI': args.contentURI
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_scanFile', nativeParam, function(result) {
-      if (result.status == 'success') {
-        if (args.successCallback) {
-            var uri = result['contentURI'];
-            args.successCallback(uri);
-        }
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-
-}
-
-ContentManager.prototype.setChangeListener = function(changeCallback) {
-  var args = validator_.validateArgs(arguments, [
-      {'name' : 'changeCallback', 'type': types_.LISTENER, 'values' : ['oncontentadded', 'oncontentupdated', 'oncontentremoved']}
-  ]);
-
-  var nativeParam = {
-  };
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_setChangeListener', nativeParam, function(result) {
-      if (result.status == 'oncontentadded') {
-        var c = result['value'];
-        var content = createContent(c);
-        args.changeCallback.oncontentadded(content);
-      }
-      if (result.status == 'oncontentupdated') {
-        var c = result['value'];
-        var content = createContent(c);
-        args.changeCallback.oncontentupdated(content);
-      }
-      if (result.status == 'oncontentremoved') {
-        var contentId = result['value'];
-        args.changeCallback.oncontentremoved(contentId);
-      }
-    });
-      // if you need synchronous result from native function using 'syncResult'.
-  } catch(e) {
-      throw e;
-  }
-}
-
-ContentManager.prototype.unsetChangeListener = function() {
-  var nativeParam = {};
-  try {
-      var syncResult = callNative('ContentManager_unsetChangeListener', nativeParam);
-  } catch(e) {
-      throw e;
-  }
-
-}
-
-ContentManager.prototype.getPlaylists = function(successCallback) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'successCallback', 'type': types_.FUNCTION},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_getPlaylists', nativeParam, function(result) {
-      if (result.status == 'success') {
-        var playlists = [];
-        for ( var i = 0; i < result.value.length; i++) {
-          var p = result.value[i];
-          var playlist = new Playlist(p.id, p.name, p.numberOfTracks, p.thumbnailURI);
-          playlists.push(playlist);
-        }
-        args.successCallback(playlists);
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-}
-
-ContentManager.prototype.createPlaylist = function(name, successCallback) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'name', 'type': types_.STRING},
-    {'name' : 'successCallback', 'type': types_.FUNCTION},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'sourcePlaylist', 'type': types_.PLATFORM_OBJECT, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'name': args.name
-  };
-
-  if (args['sourcePlaylist']) {
-    nativeParam['sourcePlaylist'] = args.sourcePlaylist;
-  }
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_createPlaylist', nativeParam, function(result) {
-      if (result.status == 'success') {
-        var p = result['value'];
-        var ret = new Playlist(p.id, p.name, p.numberOfTracks, p.thumbnailURI);
-        args.successCallback(ret);
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-      throw e;
-  }
-}
-
-ContentManager.prototype.removePlaylist = function(id) {
-  var args = validator_.validateArgs(arguments, [
-    {'name' : 'id', 'type': types_.STRING},
-    {'name' : 'successCallback', 'type': types_.FUNCTION, optional : true, nullable : true},
-    {'name' : 'errorCallback', 'type': types_.FUNCTION, optional : true, nullable : true}
-  ]);
-
-  var nativeParam = {
-    'id': args.id
-  };
-
-  try {
-    var syncResult = callNativeWithCallback('ContentManager_removePlaylist', nativeParam, function(result) {
-      if (result.status == 'success') {
-        args.successCallback();
-      }
-      else if(result.status == 'error') {
-        var err = result['value'];
-        args.errorCallback(err);
-      }
-    });
-  } catch(e) {
-    throw e;
-  }
-}
-
-
-
-exports = new ContentManager();
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
 
+//= require('common.js');
+//= require('datatypes.js');
+//= require('manager.js');
+//= require('playlist.js');
index 8fd75134f652375de5cc7ace653ce4d10b3948a0..1f87201c28c52a2f0a1d66da1d8cfcccc47e0c04 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
index 66b06845aebb3c6d9f9aaec24145ef99b48bca8d..44ef64a69158f104419aff89211aca70b91d9ff9 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
index 1c2972eef8d94a9e18fa4504ec833dcdf71b55aa..42c660c15790fb944db7b9f0a3d1db58d88c2898 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <memory>
 #include <media_content.h>
 
-#include "common/picojson.h"
 #include "common/logger.h"
+#include "common/picojson.h"
 #include "common/platform_exception.h"
 #include "common/task-queue.h"
-
-#include "content_manager.h"
+#include "content/content_manager.h"
 
 namespace extension {
 namespace content {
@@ -27,8 +26,8 @@ const std::string kPrivilegeContent = "";
 
 } // namespace
 
-using namespace common;
-using namespace extension::content;
+using common::tools::ReportSuccess;
+using common::tools::ReportError;
 
 ContentInstance::ContentInstance() {
   using std::placeholders::_1;
@@ -60,32 +59,29 @@ ContentInstance::ContentInstance() {
 }
 
 ContentInstance::~ContentInstance() {
-  LoggerE("<<endterd>>");
+  LoggerD("entered");
 }
 
-static void ReplyAsync(ContentInstance* instance, ContentCallbacks cbfunc,
-                       double callbackId, bool isSuccess, picojson::object& param) {
-  LoggerE("<<endterd>>");
-  param["callbackId"] = picojson::value(static_cast<double>(callbackId));
-  param["status"] = picojson::value(isSuccess ? "success" : "error");
-
-  picojson::value result = picojson::value(param);
+static gboolean CompletedCallback(const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("entered");
 
-  instance->PostMessage(result.serialize().c_str());
-}
+  picojson::value::object out;
+  out["callbackId"] = picojson::value(static_cast<double>(user_data->callbackId));
 
-static gboolean CompletedCallback(const std::shared_ptr<ReplyCallbackData>& user_data) {
-  LoggerE("<<endterd>>");
+  if (user_data->isSuccess) {
+    ReportSuccess(user_data->result, out);
+  } else {
+    ReportError(out);
+  }
 
-  picojson::value::object reply;
-  reply["value"] = user_data->result;
-  ReplyAsync(user_data->instance,user_data->cbType,user_data->callbackId,user_data->isSuccess,reply);
+  user_data->instance->PostMessage(picojson::value(out).serialize().c_str());
 
   return false;
 }
 
 static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
-  LoggerE("<<endterd>>");
+  LoggerD("entered");
+
   user_data->isSuccess = true;
   ContentCallbacks cbType = user_data->cbType;
   switch(cbType) {
@@ -103,7 +99,11 @@ static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
     }
     case ContentManagerScanfileCallback: {
       std::string contentURI = user_data->args.get("contentURI").get<std::string>();
-      ContentManager::getInstance()->scanFile(contentURI);
+      int res = ContentManager::getInstance()->scanFile(contentURI);
+      if (res != MEDIA_CONTENT_ERROR_NONE) {
+        LOGGER(ERROR) << "Scan file failed, error: " << res;
+        user_data->isSuccess = false;
+      }
       break;
     }
     case ContentManagerGetplaylistsCallback: {
@@ -147,14 +147,14 @@ static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
       //ContentManagerPlaylistSetOrderCallback
     }
     case ContentManagerPlaylistMoveCallback: {
-      std::string playlist_id = user_data->args.get("playlist_id").get<std::string>();   
+      std::string playlist_id = user_data->args.get("playlist_id").get<std::string>();
       double member_id = user_data->args.get("member_id").get<double>();
-      double delta = user_data->args.get("delta").get<double>();  
+      double delta = user_data->args.get("delta").get<double>();
       ContentManager::getInstance()->playlistMove(user_data);
       break;
     }
     case ContentManagerErrorCallback: {
-      UnknownException err("DB Connection is failed.");
+      common::UnknownException err("DB Connection is failed.");
       user_data->isSuccess = false;
       user_data->result = err.ToJSON();
       break;
@@ -167,51 +167,59 @@ static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
   return NULL;
 }
 
-static void changedContentCallback(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) {
+static void changedContentCallback(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");
+
+  if (error != MEDIA_CONTENT_ERROR_NONE) {
+    LOGGER(ERROR) << "Media content changed callback error: " << error;
+    return;
+  }
+
+  if (update_item != MEDIA_ITEM_FILE) {
+    LOGGER(DEBUG) << "Media item is not file, skipping.";
+    return;
+  }
 
   int ret;
-  ReplyCallbackData *cbData = static_cast<ReplyCallbackData*>(user_data);
-  picojson::object reply;
-
-  picojson::object o;
-  if( error == MEDIA_CONTENT_ERROR_NONE) {
-    if( update_item == MEDIA_ITEM_FILE) {
-      if(update_type == MEDIA_CONTENT_INSERT || update_type == MEDIA_CONTENT_UPDATE) {
-        media_info_h media = NULL;
-        std::string id(uuid);
-        ret = media_info_get_media_from_db(id.c_str(), &media);
-        if (ret == MEDIA_CONTENT_ERROR_NONE && media != NULL) {
-          contentToJson(media, o);
-          reply["value"] = picojson::value(o);
-          if (update_type == MEDIA_CONTENT_INSERT) {
-            reply["status"] = picojson::value("oncontentadded");
-          }
-          else if (update_type == MEDIA_CONTENT_UPDATE) {
-            reply["status"] = picojson::value("oncontentupdated");
-          }
-        }
-      }
-      else {
-        reply["value"] = picojson::value(std::string(uuid));
-        reply["status"] = picojson::value("oncontentremoved");
+  ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& obj = result.get<picojson::object>();
+
+  if (update_type == MEDIA_CONTENT_INSERT || update_type == MEDIA_CONTENT_UPDATE) {
+    media_info_h media = NULL;
+    ret = media_info_get_media_from_db(uuid, &media);
+    if (ret == MEDIA_CONTENT_ERROR_NONE && media != NULL) {
+      picojson::object o;
+      contentToJson(media, o);
+      ReportSuccess(picojson::value(o), obj);
+
+      if (update_type == MEDIA_CONTENT_INSERT) {
+        obj["state"] = picojson::value("oncontentadded");
+      } else {
+        obj["state"] = picojson::value("oncontentupdated");
       }
     }
+  } else {
+    ReportSuccess(picojson::value(std::string(uuid)), obj);
+    obj["state"] = picojson::value("oncontentremoved");
   }
-  else {
-    return;
-  }
-  reply["callbackId"] = picojson::value(static_cast<double>(cbData->callbackId));
-  picojson::value result = picojson::value(reply);
+
+  obj["listenerId"] = cbData->args.get("listenerId");
   cbData->instance->PostMessage(result.serialize().c_str());
-  delete cbData;
 }
 
 
 #define CHECK_EXIST(args, name, out) \
   if (!args.contains(name)) {\
-    ReportError(TypeMismatchException(name" is required argument"), out);\
+    ReportError(common::TypeMismatchException(name" is required argument"), out);\
     return;\
   }
 
@@ -225,7 +233,7 @@ void ContentInstance::ContentManagerUpdate(const picojson::value& args, picojson
     }
   }
   else {
-    ReportError(UnknownException("DB connection is failed."),out);
+    ReportError(common::UnknownException("DB connection is failed."),out);
   }
 }
 void ContentInstance::ContentManagerUpdatebatch(const picojson::value& args, picojson::object& out) {
@@ -281,7 +289,7 @@ void ContentInstance::ContentManagerFind(const picojson::value& args, picojson::
   }
 
   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
-  
+
 }
 void ContentInstance::ContentManagerScanfile(const picojson::value& args, picojson::object& out) {
   CHECK_EXIST(args, "callbackId", out)
@@ -300,27 +308,24 @@ void ContentInstance::ContentManagerScanfile(const picojson::value& args, picojs
   }
   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
 }
-void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args, picojson::object& out) {
-  CHECK_EXIST(args, "callbackId", out)
 
-  double callbackId = args.get("callbackId").get<double>();
-//  std::shared_ptr<ReplyCallbackData>cbData(new ReplyCallbackData);
+void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
+                                                      picojson::object& out) {
+  CHECK_EXIST(args, "listenerId", out)
 
-  ReplyCallbackData *cbData = new ReplyCallbackData();
+  ReplyCallbackDatacbData = new ReplyCallbackData();
 
-  cbData->callbackId = callbackId;
   cbData->instance = this;
   cbData->args = args;
-  if(ContentManager::getInstance()->isConnected()) {
+  if (ContentManager::getInstance()->isConnected()) {
     cbData->cbType = ContentManagerSetchangelistenerCallback;
-  }
-  else {
+  } else {
     cbData->cbType = ContentManagerErrorCallback;
   }
 
-  ContentManager::getInstance()->setChangeListener(changedContentCallback,static_cast<void*>(cbData));
-
+  ContentManager::getInstance()->setChangeListener(changedContentCallback, static_cast<void*>(cbData));
 }
+
 void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out) {
 
   ContentManager::getInstance()->unSetChangeListener();
@@ -399,7 +404,7 @@ void ContentInstance::ContentManagerPlaylistAdd(const picojson::value& args, pic
     }
   }
   else {
-    ReportError(UnknownException("DB connection is failed."),out);
+    ReportError(common::UnknownException("DB connection is failed."),out);
   }
 }
 
@@ -451,7 +456,7 @@ void ContentInstance::ContentManagerPlaylistRemove(const picojson::value& args,
     }
   }
   else {
-    ReportError(UnknownException("DB connection is failed."),out);
+    ReportError(common::UnknownException("DB connection is failed."),out);
   }
 }
 
@@ -510,20 +515,21 @@ void ContentInstance::ContentManagerPlaylistMove(const picojson::value& args, pi
   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
 }
 
-void ContentInstance::ContentManagerAudioGetLyrics(const picojson::value& args, picojson::object& out) {
+void ContentInstance::ContentManagerAudioGetLyrics(const picojson::value& args,
+                                                   picojson::object& out) {
   int ret;
   picojson::object lyrics;
-  if(ContentManager::getInstance()->isConnected()) {
-    ret = ContentManager::getInstance()->getLyrics(args,lyrics);
-    if(ret != MEDIA_CONTENT_ERROR_NONE) {
-      ReportError(ContentManager::getInstance()->convertError(ret),out);
+  if (ContentManager::getInstance()->isConnected()) {
+    ret = ContentManager::getInstance()->getLyrics(args, lyrics);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      ReportError(ContentManager::getInstance()->convertError(ret), out);
     }
     else {
-      ReportSuccess(picojson::value(lyrics),out);
+      ReportSuccess(picojson::value(lyrics), out);
     }
   }
   else {
-    ReportError(UnknownException("DB connection is failed."),out);
+    ReportError(common::UnknownException("DB connection is failed."), out);
   }
 }
 #undef CHECK_EXIST
index c930dfe196162c25de671dc85a409ec845045bb2..2483ac6b224101d5df2450b19354d1236f4ca0cc 100755 (executable)
@@ -11,14 +11,14 @@ namespace extension {
 namespace content {
 
 enum ContentCallbacks {
-  ContentManagerFindCallback, 
-  ContentManagerScanfileCallback, 
-  ContentManagerUnsetchangelistenerCallback, 
-  ContentManagerSetchangelistenerCallback, 
-  ContentManagerGetdirectoriesCallback, 
-  ContentManagerUpdatebatchCallback, 
-  ContentManagerRemoveplaylistCallback, 
-  ContentManagerCreateplaylistCallback, 
+  ContentManagerFindCallback,
+  ContentManagerScanfileCallback,
+  ContentManagerUnsetchangelistenerCallback,
+  ContentManagerSetchangelistenerCallback,
+  ContentManagerGetdirectoriesCallback,
+  ContentManagerUpdatebatchCallback,
+  ContentManagerRemoveplaylistCallback,
+  ContentManagerCreateplaylistCallback,
   ContentManagerGetplaylistsCallback,
   ContentManagerPlaylistAddbatchCallback,
   ContentManagerPlaylistGetCallback,
index 089b201b5664f1bc9159421e566f45b588e5ef07..be0b63f1074393ad0ca2e6e12094732e9f079fc2 100755 (executable)
@@ -154,7 +154,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
           o["width"] = picojson::value(static_cast<double>(tmpInt));
         }
         if(MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt) ) {
-          o["height"] = picojson::value(static_cast<double>(tmpInt));          
+          o["height"] = picojson::value(static_cast<double>(tmpInt));
         }
         picojson::object geo;
         std::string str_latitude;
@@ -198,7 +198,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
           }
           o["orientation"] = picojson::value(ori);
         }
-        
+
       }
 
     }
@@ -227,7 +227,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
         }
         if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt) ) {
           o["duration"] = picojson::value(static_cast<double>(tmpInt));
-        }        
+        }
       }
       picojson::object geo;
       if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble) ) {
@@ -235,7 +235,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
       }
       if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble) ) {
         geo["longitude"] = picojson::value(tmpDouble);
-      }      
+      }
       o["geolocation"] = picojson::value(geo);
     }
     else if( type == MEDIA_CONTENT_TYPE_SOUND || type == MEDIA_CONTENT_TYPE_MUSIC ) {
@@ -245,7 +245,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
         if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr) ) {
           if (tmpStr) {
             struct tm *result = (struct tm *)calloc(1, sizeof(struct tm));
-            
+
             if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
                 LoggerD( "Couldn't convert supplied date.");
             }
@@ -319,7 +319,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
           }
         }
         if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt) ) {
-          o["duration"] = picojson::value(static_cast<double>(tmpInt));          
+          o["duration"] = picojson::value(static_cast<double>(tmpInt));
         }
       }
     }
@@ -339,12 +339,12 @@ void contentToJson(media_info_h info, picojson::object& o) {
   ret = media_info_get_display_name(info, &tmpStr);
   if(ret == MEDIA_CONTENT_ERROR_NONE) {
     if(tmpStr) {
-      o["name"] = picojson::value(std::string(tmpStr));      
+      o["name"] = picojson::value(std::string(tmpStr));
       free(tmpStr);
       tmpStr = NULL;
     }
   }
+
   ret = media_info_get_mime_type(info, &tmpStr);
   if(ret == MEDIA_CONTENT_ERROR_NONE) {
     if(tmpStr) {
@@ -352,7 +352,7 @@ void contentToJson(media_info_h info, picojson::object& o) {
       free(tmpStr);
       tmpStr = NULL;
     }
-  }    
+  }
   ret = media_info_get_title(info, &tmpStr);
   if(ret == MEDIA_CONTENT_ERROR_NONE) {
     if(tmpStr) {
@@ -396,18 +396,18 @@ void contentToJson(media_info_h info, picojson::object& o) {
   }
   ret = media_info_get_favorite(info, &tmpBool);
   if(ret == MEDIA_CONTENT_ERROR_NONE) {
-    o["isFavorite"] = picojson::value(tmpBool);    
+    o["isFavorite"] = picojson::value(tmpBool);
   }
   ret = media_info_get_modified_time(info, &tmpDate);
   if(ret == MEDIA_CONTENT_ERROR_NONE) {
     std::stringstream str_date;
     str_date << tmpDate;
     o["modifiedDate"] = picojson::value(str_date.str());
-  }  
+  }
 }
 
 static int setContent(media_info_h media, picojson::value content) {
-  
+
   int ret;
   std::string name = content.get("name").to_str();
   std::string description = content.get("description").to_str();
@@ -489,7 +489,7 @@ static bool media_foreach_content_cb(media_info_h media, void *user_data) {
   picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
   picojson::value::object o;
   contentToJson(media, o);
-  contents->push_back(picojson::value(o));  
+  contents->push_back(picojson::value(o));
   return true;
 }
 
@@ -544,11 +544,11 @@ static bool playlist_foreach_cb(media_playlist_h playlist, void *user_data) {
 }
 
 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media, void *user_data) {
-  
+
   picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
   picojson::value::object o;
   char *name = NULL;
-  
+
   media_info_get_display_name(media, &name);
   o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
   contentToJson(media, o);
@@ -584,13 +584,13 @@ bool ContentManager::isConnected() {
 }
 
 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
-  
+
   picojson::value::array pico_dirs;
-  
+
   int ret = MEDIA_CONTENT_ERROR_NONE;
   filter_h filter = NULL;
   std::vector<media_folder_h> dirs;
-  
+
   ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &dirs);
 
   if (ret == MEDIA_CONTENT_ERROR_NONE) {
@@ -619,7 +619,7 @@ void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& us
       }
 
       char tmp[128];
-      ctime_r(&date, tmp);    
+      ctime_r(&date, tmp);
       o["modifiedDate"] = picojson::value(std::string(tmp));
       pico_dirs.push_back(picojson::value(o));
 
@@ -654,46 +654,44 @@ void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
       media_filter_destroy(filter);
     }
   };
-  if (user_data->args.contains("filter")) {
+  if (!IsNull(user_data->args.get("filter"))) {
     ContentFilter filterMechanism;
     std::string query;
     picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
     if (filterMechanism.buildQuery(
-            FromJson<picojson::object>(argsObject, "filter"), &query)) {
+        FromJson<picojson::object>(argsObject, "filter"), &query)) {
       ret = media_filter_set_condition(filter, query.c_str(),
-                                       MEDIA_CONTENT_COLLATE_DEFAULT);
+          MEDIA_CONTENT_COLLATE_DEFAULT);
       if (MEDIA_CONTENT_ERROR_NONE != ret) {
       }
     }
   }
-  if(user_data->args.contains("count")) {
+  if (!IsNull(user_data->args.get("count"))) {
     count = user_data->args.get("count").get<double>();
   } else {
-    count = 100; //TODO rethink proper default count setting
+    count = -1;
   }
-  if(user_data->args.contains("offset")) {
+  if (!IsNull(user_data->args.get("offset"))) {
     offset = user_data->args.get("offset").get<double>();
-  }
-  else {
-    offset = 0;
+  } else {
+    offset = -1;
   }
   ret = media_filter_set_offset(filter, offset, count);
-  if ( MEDIA_CONTENT_ERROR_NONE != ret) {
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
     LoggerD("A platform error occurs in media_filter_set_offset.");
   }
-  if(user_data->args.contains("directoryId")) {
+  if (!IsNull(user_data->args.get("directoryId"))) {
     dirId = user_data->args.get("directoryId").get<std::string>();
     ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
-  }
-  else {
+  } else {
     ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
   }
 
   if (ret == MEDIA_CONTENT_ERROR_NONE) {
+    LoggerD("enter");
     user_data->isSuccess = true;
     user_data->result = picojson::value(arrayContent);
-  }
-  else {
+  } else {
     UnknownException err("The iteration is failed in platform.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
@@ -720,19 +718,19 @@ void ContentManager::unSetChangeListener() {
   }
 }
 
-void ContentManager::createPlaylist(std::string name, 
+void ContentManager::createPlaylist(std::string name,
   const std::shared_ptr<ReplyCallbackData>& user_data) {
-  
+
   media_playlist_h     playlist = NULL;
-  
+
   int ret = media_playlist_insert_to_db(name.c_str(),&playlist);
-  if(ret != MEDIA_CONTENT_ERROR_NONE) { 
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("creation of playlist is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();    
+    user_data->result = err.ToJSON();
   }
   picojson::value::object o;
-  
+
   if( playlist != NULL) {
     int id,cnt;
     char* thumb_path = NULL;
@@ -760,7 +758,7 @@ void ContentManager::createPlaylist(std::string name,
       LoggerD("Invalid thumbnail path for playlist.");
     }
     if( media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
-      o["name"] = picojson::value(std::string(name));      
+      o["name"] = picojson::value(std::string(name));
       free(name);
     }
     else {
@@ -785,21 +783,21 @@ void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user
   filter_h     filter;
   media_filter_create(&filter);
   picojson::value::array playlists;
-  
+
   ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb, static_cast<void*>(&playlists));
 
   if(ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("Getting playlist is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();      
+    user_data->result = err.ToJSON();
   }
   user_data->isSuccess = true;
   user_data->result = picojson::value(playlists);
 }
 
-void ContentManager::removePlaylist(std::string playlistId, 
+void ContentManager::removePlaylist(std::string playlistId,
   const std::shared_ptr<ReplyCallbackData>& user_data) {
-  
+
   int id = std::atoi(playlistId.c_str());
   if(id == 0) {
     UnknownException err("PlaylistId is wrong.");
@@ -812,7 +810,7 @@ void ContentManager::removePlaylist(std::string playlistId,
   if(ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("Removal of playlist is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();      
+    user_data->result = err.ToJSON();
   }
 }
 
@@ -843,7 +841,7 @@ int ContentManager::updateBatch(picojson::value args) {
     std::string id = content.get("id").to_str();
     media_info_h media = NULL;
     ret = media_info_get_media_from_db (id.c_str(), &media);
-    dlog_print(DLOG_INFO, "DYKIM", "ContentManager::update id:%s",id.c_str());          
+    dlog_print(DLOG_INFO, "DYKIM", "ContentManager::update id:%s",id.c_str());
     if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
       setContent(media, content);
       ret = media_info_update_to_db(media);
@@ -866,7 +864,7 @@ int ContentManager::playlistAdd(std::string playlist_id, std::string content_id)
   if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
     ret = media_playlist_add_media(playlist, content_id.c_str());
     if (ret != MEDIA_CONTENT_ERROR_NONE) {
-      LoggerD("The content(id:%s) can't add to playlist",content_id.c_str());      
+      LoggerD("The content(id:%s) can't add to playlist",content_id.c_str());
     }
 
     ret = media_playlist_update_to_db(playlist);
@@ -877,7 +875,7 @@ int ContentManager::playlistAdd(std::string playlist_id, std::string content_id)
   else {
     LoggerD("Playlist(id:%s) is not exist",playlist_id.c_str());
   }
-  
+
   media_playlist_destroy(playlist);
   return ret;
 }
@@ -890,7 +888,7 @@ int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
   if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
     ret = media_playlist_remove_media(playlist, member_id);
     if (ret != MEDIA_CONTENT_ERROR_NONE) {
-      LoggerD("The content can't remove to playlist");      
+      LoggerD("The content can't remove to playlist");
     }
 
     ret = media_playlist_update_to_db(playlist);
@@ -902,26 +900,26 @@ int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
     LoggerD("Playlist(id:%s) is not exist",playlist_id.c_str());
   }
   media_playlist_destroy(playlist);
-  
+
   return ret;
 }
 
 
 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
-  
+
   int ret = MEDIA_CONTENT_ERROR_NONE;
   std::string playlist_id = user_data->args.get("playlist_id").get<std::string>();
 
-  media_playlist_h playlist = NULL;  
+  media_playlist_h playlist = NULL;
   ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
 
-  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) { 
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
     UnknownException err("Getting playlist is failed.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
     return;
   }
-  
+
   std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
   for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); it++) {
     picojson::value content = *it;
@@ -942,13 +940,13 @@ void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>&
 }
 
 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
-  
+
   int ret = MEDIA_CONTENT_ERROR_NONE;
-  media_playlist_h playlist = NULL;  
+  media_playlist_h playlist = NULL;
 
   std::string playlist_id = user_data->args.get("playlist_id").get<std::string>();
   ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
-  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) { 
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
     UnknownException err("Getting playlist is failed.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
@@ -961,7 +959,7 @@ void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_
     UnknownException err("Creating a filter is failed.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
-    return;    
+    return;
   }
 
   int count = user_data->args.get("count").get<double>();
@@ -987,13 +985,13 @@ void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_
 }
 
 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
   int ret = MEDIA_CONTENT_ERROR_NONE;
-  media_playlist_h playlist = NULL;  
+  media_playlist_h playlist = NULL;
 
   std::string playlist_id = user_data->args.get("playlist_id").get<std::string>();
   ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
-  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) { 
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
     UnknownException err("Getting playlist is failed.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
@@ -1014,7 +1012,7 @@ void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData
   if (ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("Removing the contents is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();    
+    user_data->result = err.ToJSON();
   }
   else {
     user_data->isSuccess = true;
@@ -1036,17 +1034,17 @@ void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>&
   }
 
   int cnt;
-  std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();  
-  
+  std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
+
   ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
 
   if ( cnt != members.size() ) {
     InvalidValuesException err("The items array does not contain all items from the playlist.");
     user_data->isSuccess = false;
     user_data->result = err.ToJSON();
-    return;    
+    return;
   }
-  
+
   for( int i = 0; i < members.size(); i++ ) {
     int member_id = static_cast<int>(members.at(i).get<double>());
     ret = media_playlist_set_play_order(playlist, member_id, i);
@@ -1054,12 +1052,12 @@ void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>&
       LoggerD("Removing a content is failed.");
     }
   }
-  
+
   ret = media_playlist_update_to_db(playlist);
   if (ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("Removing the contents is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();    
+    user_data->result = err.ToJSON();
   }
   else {
     user_data->isSuccess = true;
@@ -1099,11 +1097,11 @@ void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user
   if (ret != MEDIA_CONTENT_ERROR_NONE) {
     UnknownException err("Updateing play_order is failed.");
     user_data->isSuccess = false;
-    user_data->result = err.ToJSON();    
+    user_data->result = err.ToJSON();
   }
   else {
     user_data->isSuccess = true;
-  }  
+  }
 }
 
 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
diff --git a/src/content/js/common.js b/src/content/js/common.js
new file mode 100644 (file)
index 0000000..15b346f
--- /dev/null
@@ -0,0 +1,44 @@
+/* global tizen, xwalk, extension */
+
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var EditManager = function() {
+  this.isAllowed = false;
+};
+
+EditManager.prototype.allow = function() {
+  this.isAllowed = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.isAllowed = false;
+};
+
+var edit_ = new EditManager();
+
+var SCHEMA = 'file://';
+
+function convertUriToPath_(uri) {
+  if (0 === uri.indexOf(SCHEMA)) {
+    return uri.substring(SCHEMA.length);
+  }
+
+  return uri;
+}
+
+function convertPathToUri_(path) {
+  if (0 === path.indexOf(SCHEMA)) {
+    return path;
+  }
+
+  return SCHEMA + path;
+}
diff --git a/src/content/js/datatypes.js b/src/content/js/datatypes.js
new file mode 100644 (file)
index 0000000..7003d32
--- /dev/null
@@ -0,0 +1,275 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ContentDirectoryStorageType = {
+  INTERNAL: 'INTERNAL',
+  EXTERNAL: 'EXTERNAL'
+};
+
+var ContentType = {
+  IMAGE: 'IMAGE',
+  VIDEO: 'VIDEO',
+  AUDIO: 'AUDIO',
+  OTHER: 'OTHER'
+};
+
+var AudioContentLyricsType = {
+  SYNCHRONIZED: 'SYNCHRONIZED',
+  UNSYNCHRONIZED: 'UNSYNCHRONIZED'
+};
+
+var ImageContentOrientation = {
+  NORMAL: 'NORMAL',
+  FLIP_HORIZONTAL: 'FLIP_HORIZONTAL',
+  ROTATE_180: 'ROTATE_180',
+  FLIP_VERTICAL: 'FLIP_VERTICAL',
+  TRANSPOSE: 'TRANSPOSE',
+  ROTATE_90: 'ROTATE_90',
+  TRANSVERSE: 'TRANSVERSE',
+  ROTATE_270: 'ROTATE_270'
+};
+
+function ContentDirectory() {
+  // TODO(r.galka)
+  //SetReadOnlyProperty(this, 'id', null); // read only property
+  //SetReadOnlyProperty(this, 'directoryURI', null); // read only property
+  //SetReadOnlyProperty(this, 'title', null); // read only property
+  //SetReadOnlyProperty(this, 'storageType', null); // read only property
+  //SetReadOnlyProperty(this, 'modifiedDate', null); // read only property
+}
+
+
+function Content(data) {
+  var editableAttributes = ['name', 'rating', 'description'];
+  var id;
+  var name;
+  var type;
+  var mimeType;
+  var title;
+  var contentURI;
+  var thumbnailURIs = null;
+  var releaseDate = null;
+  var modifiedDate = null;
+  var size;
+  var description = null;
+  var rating;
+  var isFavorite;
+
+  Object.defineProperties(this, {
+    editableAttributes: {
+      value: editableAttributes,
+      writable: false,
+      enumerable: true
+    },
+    id: {
+      get: function() {
+        return id;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return name;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          name = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return type;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          type = converter_.toEnum(v, Object.keys(ContentType), false);
+        }
+      },
+      enumerable: true
+    },
+    mimeType: {
+      get: function() {
+        return mimeType;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          mimeType = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    title: {
+      get: function() {
+        return title;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          title = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    contentURI: {
+      get: function() {
+        return contentURI;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          contentURI = convertPathToUri_(v);
+        }
+      },
+      enumerable: true
+    },
+    thumbnailURIs: {
+      get: function() {
+        return thumbnailURIs;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          thumbnailURIs = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    releaseDate: {
+      get: function() {
+        return releaseDate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          releaseDate = !type_.isNull(v) ? new Date(v) : null;
+        }
+      },
+      enumerable: true
+    },
+    modifiedDate: {
+      get: function() {
+        return modifiedDate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          modifiedDate = !type_.isNull(v) ? new Date(v) : null;
+        }
+      },
+      enumerable: true
+    },
+    size: {
+      get: function() {
+        return size;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          size = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    description: {
+      get: function() {
+        return description;
+      },
+      set: function(v) {
+        description = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    rating: {
+      get: function() {
+        return rating;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          rating = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    isFavorite: {
+      get: function() {
+        return isFavorite;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          isFavorite = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+
+function VideoContent() {
+  // TODO(r.galka)
+  //this.geolocation = null;
+  //SetReadOnlyProperty(this, 'album', null); // read only property
+  //SetReadOnlyProperty(this, 'artists', null); // read only property
+  //SetReadOnlyProperty(this, 'duration', null); // read only property
+  //SetReadOnlyProperty(this, 'width', null); // read only property
+  //SetReadOnlyProperty(this, 'height', null); // read only property
+}
+
+VideoContent.prototype = new Content();
+VideoContent.prototype.constructor = VideoContent;
+
+
+function AudioContentLyrics() {
+  // TODO(r.galka)
+  //SetReadOnlyProperty(this, 'type', null); // read only property
+  //SetReadOnlyProperty(this, 'timestamps', null); // read only property
+  //SetReadOnlyProperty(this, 'texts', null); // read only property
+}
+
+
+function AudioContent() {
+  // TODO(r.galka)
+  //SetReadOnlyProperty(this, 'album', null); // read only property
+  //SetReadOnlyProperty(this, 'genres', null); // read only property
+  //SetReadOnlyProperty(this, 'artists', null); // read only property
+  //SetReadOnlyProperty(this, 'composers', null); // read only property
+  //SetReadOnlyProperty(this, 'lyrics', null); // read only property
+  //SetReadOnlyProperty(this, 'copyright', null); // read only property
+  //SetReadOnlyProperty(this, 'bitrate', null); // read only property
+  //SetReadOnlyProperty(this, 'trackNumber', null); // read only property
+  //SetReadOnlyProperty(this, 'duration', null); // read only property
+}
+
+AudioContent.prototype = new Content();
+AudioContent.prototype.constructor = AudioContent;
+
+
+function ImageContent() {
+  // TODO(r.galka)
+  //this.geolocation = null;
+  //SetReadOnlyProperty(this, 'width', null); // read only property
+  //SetReadOnlyProperty(this, 'height', null); // read only property
+  //this.orientation = null;
+}
+
+ImageContent.prototype = new Content();
+ImageContent.prototype.constructor = ImageContent;
+
+
+function PlaylistItem() {
+  // TODO(r.galka)
+  //SetReadOnlyProperty(this, 'content', null); // read only property
+}
diff --git a/src/content/js/manager.js b/src/content/js/manager.js
new file mode 100644 (file)
index 0000000..91ecc8d
--- /dev/null
@@ -0,0 +1,245 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function _ContentManagerChangeCallback(result) {
+  if (result.state === 'oncontentadded' || result.state === 'oncontentupdated') {
+    var content = native_.getResultObject(result);
+    native_.callIfPossible(this[result.state], new Content(content));
+  }
+  if (result.state === 'oncontentremoved') {
+    native_.callIfPossible(this.oncontentremoved, native_.getResultObject(result));
+  }
+}
+
+
+function ContentManager() {
+}
+
+ContentManager.prototype.update = function(content) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'content', type: types_.PLATFORM_OBJECT, values: tizen.Content}
+  ]);
+
+  var data = {
+    content: args.content
+  };
+
+  var result = native_.callSync('ContentManager_update', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.updateBatch = function(contents, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contents', type: types_.PLATFORM_OBJECT, values: tizen.Content},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    contents: args.contents
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_updateBatch', data, callback);
+};
+
+ContentManager.prototype.getDirectories = function(successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_getDirectories', data, callback);
+};
+
+ContentManager.prototype.find = function(successCallback, errorCallback, directoryId, filter, sortMode, count, offset) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'directoryId', type: types_.STRING, optional: true, nullable: true},
+    {
+      name: 'filter',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+      optional: true,
+      nullable: true
+    },
+    {name: 'sortMode', type: types_.PLATFORM_OBJECT, values: tizen.SortMode, optional: true, nullable: true},
+    {name: 'count', type: types_.LONG, optional: true},
+    {name: 'offset', type: types_.LONG, optional: true}
+  ]);
+
+  var data = {
+    directoryId: args.directoryId,
+    filter: utils_.repackFilter(args.filter),
+    sortMode: args.sortMode,
+    count: args.count,
+    offset: args.offset
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback, native_.getResultObject(result));
+  };
+
+  native_.call('ContentManager_find', data, callback);
+};
+
+ContentManager.prototype.scanFile = function(contentURI, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contentURI', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var path = args.contentURI.trim();
+  if (!path.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'File path is not valid.');
+  }
+
+  var data = {
+    contentURI: convertUriToPath_(path)
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback, args.contentURI);
+  };
+
+  native_.call('ContentManager_scanFile', data, callback);
+};
+
+ContentManager.prototype.setChangeListener = function(changeCallback) {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'changeCallback',
+    type: types_.LISTENER,
+    values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved']
+  }]);
+
+  var listenerId = 'ContentManagerChangeCallback';
+
+  var data = {
+    listenerId: listenerId
+  };
+
+  var callbacks = {
+    oncontentadded: args.changeCallback.oncontentadded,
+    oncontentupdated: args.changeCallback.oncontentupdated,
+    oncontentremoved: args.changeCallback.oncontentremoved
+  };
+
+  native_.addListener('ContentManagerChangeCallback',
+      _ContentManagerChangeCallback.bind(callbacks));
+
+  var result = native_.callSync('ContentManager_setChangeListener', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.unsetChangeListener = function() {
+  var data = {};
+
+  var result = native_.callSync('ContentManager_unsetChangeListener', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.getPlaylists = function(successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {};
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_getPlaylists', data, callback);
+};
+
+ContentManager.prototype.createPlaylist = function(name, successCallback, errorCallback, sourcePlaylist) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'name', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'sourcePlaylist', type: types_.PLATFORM_OBJECT, values: tizen.Playlist, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    name: args.name,
+    sourcePlaylist: args.sourcePlaylist
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_createPlaylist', data, callback);
+};
+
+ContentManager.prototype.removePlaylist = function(id, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    id: args.id
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_removePlaylist', data, callback);
+};
+
+exports = new ContentManager();
diff --git a/src/content/js/playlist.js b/src/content/js/playlist.js
new file mode 100644 (file)
index 0000000..2722e20
--- /dev/null
@@ -0,0 +1,157 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Playlist() {
+  // TODO(r.galka)
+  //SetReadOnlyProperty(this, 'id', null); // read only property
+  //this.name = null;
+  //SetReadOnlyProperty(this, 'numberOfTracks', null); // read only property
+  //this.thumbnailURI = null;
+}
+
+Playlist.prototype.add = function (item) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: tizen.Content}
+  ]);
+
+  var data = {
+    item: args.item
+  };
+
+  var result = native_.callSync('Playlist_add', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Playlist.prototype.addBatch = function (items, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.PLATFORM_OBJECT, values: tizen.Content},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    items: args.items
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('Playlist_addBatch', data, callback);
+};
+
+Playlist.prototype.remove = function (item) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: tizen.PlaylistItem}
+  ]);
+
+  var data = {
+    item: args.item
+  };
+
+  var result = native_.callSync('Playlist_remove', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Playlist.prototype.removeBatch = function (items, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.PLATFORM_OBJECT, values: tizen.PlaylistItem},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    items: args.items
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('Playlist_removeBatch', data, callback);
+};
+
+Playlist.prototype.get = function (successCallback, errorCallback, count, offset) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'count', type: types_.LONG, optional: true},
+    {name: 'offset', type: types_.LONG, optional: true}
+  ]);
+
+  var data = {
+    count: args.count,
+    offset: args.offset
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('Playlist_get', data, callback);
+};
+
+Playlist.prototype.setOrder = function (items, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.PLATFORM_OBJECT, values: tizen.PlaylistItem},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    items: args.items
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('Playlist_setOrder', data, callback);
+};
+
+Playlist.prototype.move = function (item, delta, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: tizen.PlaylistItem},
+    {name: 'delta', type: types_.LONG},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    item: args.item,
+    delta: args.delta
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('Playlist_move', data, callback);
+};