[Bookmark] Initial implementation of Bookmark
authorKamil Nowac <k.nowac@samsung.com>
Thu, 11 Dec 2014 14:47:10 +0000 (15:47 +0100)
committerRafal Galka <r.galka@samsung.com>
Tue, 13 Jan 2015 12:35:49 +0000 (21:35 +0900)
TCT Pass rate: 26 / 36

Change-Id: I70d151ae42f677e6351179bf6803d7fb549207ce
Signed-off-by: Kamil Nowac <k.nowac@samsung.com>
src/bookmark/bookmark.gyp
src/bookmark/bookmark_api.js
src/bookmark/bookmark_extension.cc
src/bookmark/bookmark_instance.cc
src/bookmark/bookmark_instance.h

index af307b37eb641da749621b5d47e51a6b73973bae..5bd3eabed0ddd795d9801ea7ea04ca1e7bc96143 100644 (file)
         'bookmark_instance.h',
       ],
       'conditions': [
-        [ 'tizen == 1', {
-            'variables': {
-              'packages': [
-                'bookmark-adaptor',
-              ]
-            },
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'bookmark-adaptor',
+            ]
+          },
         }],
       ],
     },
index 470963194cfc0753b6e379a2e1923d2cd0a2a61a..99080557e5720bfd808670d8b50df19de4c20b29 100644 (file)
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function throwException_(err) {
-  throw new tizen.WebAPIException(err.code, err.name, err.message);
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function EditManager() {
+  this.canEdit = false;
 }
 
-function _sendSyncMessage(msg) {
-  var data = null;
-  data = JSON.stringify(msg);
+EditManager.prototype.allow = function() {
+  this.canEdit = true;
+};
 
-  return JSON.parse(extension.internal.sendSyncMessage(data));
-}
+EditManager.prototype.disallow = function() {
+  this.canEdit = false;
+};
 
-function BookmarkManager() {
-}
+var _edit = new EditManager();
+
+function BookmarkManager() {}
 
 BookmarkManager.prototype.get = function() {
-  return new BookmarkManager();
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'parentFolder',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'recursive',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  var result;
+
+  if (arguments.length === 0 || args.parentFolder === null) {
+    result = provider.getFolderItems(provider.getRootId(), args.recursive);
+    if (!result)
+      throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+    return result;
+  }
+  if (args.parentFolder.id === null || args.parentFolder.id === 0)
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+
+  result = provider.getFolderItems(args.parentFolder.id, args.recursive);
+  if (!result)
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  return result;
 };
 
-BookmarkManager.prototype.add = function(parent_folder, recursive) {
-  var msg = {
-    cmd: 'add',
-    arg: ''
-  };
+BookmarkManager.prototype.add = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'parentFolder',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.BookmarkFolder,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  if (arguments.length == 1 || args.parentFolder === null) {
+    if (args.bookmark.id) {
+      throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+    }
+    if (!provider.addToFolder(args.bookmark, provider.getRootId())) {
+      throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+    }
+    return;
+  }
+  if (!args.parentFolder.id) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+  if (!provider.addToFolder(args.bookmark, args.parentFolder.id)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+};
+
+BookmarkManager.prototype.remove = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    }
+  ]);
 
-  return _sendSyncMessage(msg).value;
+  if (!arguments.length || args.bookmark === null) {
+    if (native_.isFailure(native_.callSync('Bookmark_removeAll')))
+      throw new tizen.WebAPIException(tizen.WebAPIException.SECURITY_ERR);
+    return;
+  }
+  if (!args.bookmark.id)
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  if (native_.isFailure(native_.callSync('Bookmark_remove', {
+    id: args.bookmark.id})))
+    throw new tizen.WebAPIException(tizen.WebAPIException.SECURITY_ERR);
+
+  _edit.allow();
+  args.bookmark.id = null;
+  args.bookmark.parent = undefined;
+  _edit.disallow();
 };
 
+function BookmarkProvider() {}
+
+BookmarkProvider.prototype.addToFolder = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'parentId',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false}
+  ]);
+  var ret = native_.callSync('Bookmark_add',
+      {
+        title: args.bookmark.title,
+        url: args.bookmark.url || '/',
+        parentId: args.parentId,
+        type: args.bookmark instanceof tizen.BookmarkFolder ? 1 : 0
+      }
+      );
+  if (native_.isFailure(ret)) {
+    return false;
+  }
+  var ret_id = native_.getResultObject(ret);
+  _edit.allow();
+  args.bookmark.id = ret_id;
+  args.bookmark.parent = this.getFolder(args.parentId);
+  _edit.disallow();
+  return true;
+};
+
+BookmarkProvider.prototype.getFolder = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'id',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false
+    }
+  ]);
+  if (arguments.length === 0 || args.id <= 0)
+    return null;
+  if (args.id == this.getRootId())
+    return null;
+
+  var ret = native_.callSync('Bookmark_get', {
+    id: args.id,
+    shouldGetItems: 0
+  });
 
-BookmarkManager.prototype.remove = function(bookmark) {
-  var msg = {
-    cmd: 'remove',
-    arg: ''
-  };
+  if (native_.isFailure(ret)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
 
-  return _sendSyncMessage(msg).value;
+  var folder = native_.getResultObject(ret);
+  if (folder === undefined || folder === null)
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+
+  var obj = new tizen.BookmarkFolder(folder[0].title);
+  _edit.allow();
+  obj.id = folder[0].id;
+  obj.parent = this.getFolder(folder[0].parentId);
+  _edit.disallow();
+  return obj;
 };
 
-tizen.BookmarkItem = function(title, url) {
-  var parent;
-  var title_;
-  var url_;
+BookmarkProvider.prototype.getFolderItems = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'id',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'recursive',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var ret = native_.callSync('Bookmark_get', {
+    id: Number(args.id),
+    shouldGetItems: 1
+  });
+
+  if (native_.isFailure(ret)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var folder = native_.getResultObject(ret);
+  if (folder === undefined)
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+
+  var item;
+  var obj;
+  var result = [];
+  var len = folder.length;
+  for (var i = 0; item = folder[i], i < len; i++) {
+    if (item.type !== 0) {
+      obj = new tizen.BookmarkItem(item.title, item.url);
+      _edit.allow();
+      obj.id = item.id;
+      obj.url = item.url;
+      obj.parent = this.getFolder(item.parentId);
+      _edit.disallow();
+      result.push(obj);
+    } else {
+      obj = new tizen.BookmarkFolder(item.title);
+      _edit.allow();
+      obj.id = item.id;
+      obj.parent = this.getFolder(item.parentId);
+      _edit.disallow();
+      result.push(obj);
+      if (args.recursive) {
+        result = result.concat(this.getFolderItems(item.id, true));
+      }
+    }
+  }
+  return result;
+};
+
+BookmarkProvider.prototype.getRootId = function() {
+  var ret = native_.callSync('Bookmark_getRootId');
+  if (native_.isFailure(ret)) {
+    throw native_.getErrorObject(ret);
+  }
+  var rootId = native_.getResultObject(ret);
+  return Number(rootId);
 };
 
-tizen.BookmarkFolder = function(title) {
-  var parent;
-  var title_;
+var provider = new BookmarkProvider();
+
+tizen.BookmarkItem = function() {
+  validator_.isConstructorCall(this, tizen.BookmarkItem);
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'title',
+      type: types_.STRING,
+      optional: false
+    },
+    {
+      name: 'url',
+      type: types_.STRING,
+      optional: false
+    }
+  ]);
+  var parent_;
+  var id_ = null;
+  var url_;
+
+  Object.defineProperties(this, {
+    parent: {
+      get: function() {
+        return parent_;
+      },
+      set: function(new_parent) {
+        if (_edit.canEdit) {
+          parent_ = new_parent;
+        }
+      },
+      enumerable: true,
+      nullable: true
+    },
+    title: {
+      get: function() {
+        return args.title;
+      },
+      enumerable: true,
+      nullable: false
+    },
+    url: {
+      get: function() {
+        return args.url;
+      },
+      set: function(new_url) {
+        if (_edit.canEdit) {
+          url_ = new_url;
+        }
+      },
+      enumerable: true,
+      nullable: false
+    },
+    id: {
+      get: function() {
+        if (!id_)
+          return 0;
+        return id_;
+      },
+      set: function(new_id) {
+        if (_edit.canEdit) {
+          id_ = new_id;
+        }
+      },
+      enumerable: false,
+      nullable: true
+    }
+  });
 };
 
+tizen.BookmarkFolder = function() {
+  validator_.isConstructorCall(this, tizen.BookmarkFolder);
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'title',
+      type: types_.STRING,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var parent_;
+  var id_ = null;
+
+  Object.defineProperties(this, {
+    parent: {
+      get: function() {
+        return parent_;
+      },
+      set: function(new_parent) {
+        if (_edit.canEdit) {
+          parent_ = new_parent;
+        }
+      },
+      enumerable: true,
+      nullable: true
+    },
+    title: {
+      get: function() {
+        return args.title;
+      },
+      enumerable: true,
+      nullable: false
+    },
+    id: {
+      get: function() {
+        if (!id_)
+          return 0;
+        return id_;
+      },
+      set: function(new_id) {
+        if (_edit.canEdit) {
+          id_ = new_id;
+        }
+      },
+      enumerable: false,
+      nullable: true
+    }
+  });
+};
 exports = new BookmarkManager();
index 95a6f5b1ba8c86343d7be7981eef4822bb61db8a..6544819730643fd20469ca30011b156d64e845e5 100644 (file)
@@ -6,9 +6,9 @@
 #include "bookmark/bookmark_instance.h"
 
 namespace {
-  const char* kBookmark = "tizen.bookmark";
-  const char* kBookmarkItem = "tizen.BookmarkItem";
-  const char* kBookmarkFolder = "tizen.BookmarkFolder";
+  const char kBookmark[] = "tizen.bookmark";
+  const char kBookmarkItem[] = "tizen.BookmarkItem";
+  const char kBookmarkFolder[] = "tizen.BookmarkFolder";
 }
 
 // This will be generated from bookmark_api.js.
index f190ba0fa53511e35ce646e342748eecceb64924..211a816cc008e2d847a00676bd79311cdb22ba5f 100644 (file)
 
 #include "bookmark/bookmark_instance.h"
 
-#include <web/web_bookmark.h>
+#include <web/bookmark-adaptor.h>
 #include <string>
 
-#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/converter.h"
 
 namespace extension {
 namespace bookmark {
 
 namespace {
-  const char* kGet = "get";
-  const char* kAdd = "add";
-  const char* kRemove = "remove";
-  const char* kCmd = "cmd";
-  const char* kArg = "arg";
-  const char* kError = "error";
-  const char* kValue = "value";
-  const char* kNotImplemented = "Not implemented";
-}
+  const char kGet[] = "Bookmark_get";
+  const char kAdd[] = "Bookmark_add";
+  const char kRemove[] = "Bookmark_remove";
+  const char kRemoveAll[] = "Bookmark_removeAll";
+  const char kGetRootId[] = "Bookmark_getRootId";
+  const char kId[] = "id";
+  const char kTitle[] = "title";
+  const char kType[] = "type";
+  const char kParentId[] = "parentId";
+  const char kUrl[] = "url";
+}  // namespace
 
 BookmarkInstance::BookmarkInstance() {
-  int ret = bp_bookmark_adaptor_initialize();
-  if (ret)
-    LoggerE("bp_bookmark_adaptor_initialize failed (%d)", ret);
+  using namespace std::placeholders;
+#define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&BookmarkInstance::x, this, _1, _2));
+  REGISTER_SYNC(kGet, Bookmark_get);
+  REGISTER_SYNC(kAdd, Bookmark_add);
+  REGISTER_SYNC(kRemove, Bookmark_remove);
+  REGISTER_SYNC(kRemoveAll, Bookmark_removeAll);
+  REGISTER_SYNC(kGetRootId, Bookmark_getRootId);
+#undef REGISTER_SYNC
+  if (bp_bookmark_adaptor_initialize()) {
+    throw common::NotSupportedException("Fail: Bookmark not supported");
+  }
 }
 
 BookmarkInstance::~BookmarkInstance() {
-  int ret = bp_bookmark_adaptor_deinitialize();
-  if (ret)
-    LoggerE("bp_bookmark_adaptor_deinitialize failed (%d)", ret);
+  if (bp_bookmark_adaptor_deinitialize()) {
+    throw common::NotSupportedException("Fail: Deinitialize Bookmark");
+  }
 }
 
-void BookmarkInstance::HandleMessage(const char* msg) {}
+bool BookmarkInstance::bookmark_foreach(
+    Context& ctx, bp_bookmark_info_fmt& info) {
+  int ids_count = 0;
+  int *ids = NULL;
+  BookmarkObject item;
+  if (bp_bookmark_adaptor_get_full_ids_p(&ids, &ids_count) < 0)
+    return false;
+  if (ids_count > 0) {
+    for (int i = 0; i < ids_count; i++) {
+      bp_bookmark_adaptor_get_easy_all(ids[i], &info);
+      item.id = ids[i];
+      item.bookmark_info = info;
+      if ((ctx.shouldGetItems && item.bookmark_info.parent != ctx.id) ||
+        (!ctx.shouldGetItems && item.id != ctx.id))
+        continue;
+      ctx.folders.push_back(item);
+    }
+  }
+  free(ids);
+  return true;
+}
+
+void BookmarkInstance::Bookmark_get(
+    const picojson::value& arg, picojson::object& o) {
+  Context ctx = {0};
+  bp_bookmark_info_fmt info = {0};
+  picojson::value::array arr;
 
-void BookmarkInstance::HandleSyncMessage(const char* msg) {
-  picojson::value v;
-  std::string err;
+  ctx.shouldGetItems = arg.get("shouldGetItems").get<double>();
+  ctx.id             = arg.get(kId).get<double>();
 
-  picojson::parse(v, msg, msg + strlen(msg), &err);
-  if (!err.empty()) {
+  if (!bookmark_foreach(ctx, info)) {
+    ReportError(o);
     return;
   }
 
-  std::string cmd = v.get(kCmd).to_str();
-  picojson::value arg = v.get(kArg);
-  picojson::value::object o;
+  std::vector<BookmarkObject>::iterator it;
+  for (it = ctx.folders.begin(); it!= ctx.folders.end(); ++it) {
+    picojson::object obj;
+    BookmarkObject entry = *it;
+
+    obj[kTitle] = picojson::value(entry.bookmark_info.title);
+    obj[kId] = picojson::value(std::to_string(entry.id));
+    obj[kType] = picojson::value(std::to_string(entry.bookmark_info.type));
+    obj[kParentId] = picojson::value(std::to_string(
+        entry.bookmark_info.parent));
+    obj[kUrl] = picojson::value(entry.bookmark_info.url);
 
-  if (cmd == kGet) {
-    HandleGet(arg, o);
-  } else if (cmd == kAdd) {
-    HandleAdd(arg, o);
-  } else if (cmd == kRemove) {
-    HandleRemove(arg, o);
+    arr.push_back(picojson::value(obj));
   }
+  ReportSuccess(picojson::value(arr), o);
+}
 
-  if (o.empty())
-    o[kError] = picojson::value(true);
+void BookmarkInstance::Bookmark_add(
+    const picojson::value& arg, picojson::object& o) {
+  int saved_id =-1;
+  bp_bookmark_info_fmt data = {0};
 
-  SendSyncReply(picojson::value(o).serialize().c_str());
-}
+  data.title = const_cast<char*>(arg.get(kTitle).to_str().c_str());
+  data.parent = arg.get(kParentId).get<double>();
+  data.type = arg.get(kType).get<double>();
+  data.url = const_cast<char*>(arg.get(kUrl).to_str().c_str());
 
-void BookmarkInstance::HandleGet(const picojson::value& arg, picojson::object& o) {
-  o[kValue] = picojson::value(kNotImplemented);
+  if (bp_bookmark_adaptor_create(&saved_id) < 0) {
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_title(saved_id, data.title) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_parent_id(saved_id, data.parent) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_type(saved_id, data.type) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_url(saved_id, data.url) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(saved_id)), o);
 }
 
-void BookmarkInstance::HandleAdd(const picojson::value& arg, picojson::object& o) {
-  o[kValue] = picojson::value(kNotImplemented);
+void BookmarkInstance::Bookmark_remove(
+    const picojson::value& arg, picojson::object& o) {
+  int id = common::stol(
+      common::FromJson<std::string>(arg.get<picojson::object>(), kId));
+  if (bp_bookmark_adaptor_delete(id) < 0) {
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_clear_deleted_ids() < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(o);
 }
 
-void BookmarkInstance::HandleRemove(const picojson::value& arg, picojson::object& o) {
-  o[kValue] = picojson::value(kNotImplemented);
+void BookmarkInstance::Bookmark_removeAll(
+    const picojson::value& msg, picojson::object& o) {
+  if (bp_bookmark_adaptor_reset() < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(o);
 }
 
-} //namespace bookmark
-} //namespace extension
+void BookmarkInstance::Bookmark_getRootId(
+    const picojson::value& msg, picojson::object& o) {
+  int rootId(0);
+  if (bp_bookmark_adaptor_get_root(&rootId) < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(rootId)), o);
+}
+}  // namespace bookmark
+}  // namespace extension
index 394307999871dfd582cdcac286b7466d04aa03ca..5326b445cff4661ee57517dfe5f91084a9d5ac0c 100644 (file)
@@ -5,27 +5,39 @@
 #ifndef BOOKMARK_BOOKMARK_INSTANCE_H_
 #define BOOKMARK_BOOKMARK_INSTANCE_H_
 
+#include <web/web_bookmark.h>
+#include <vector>
+
 #include "common/extension.h"
 #include "common/picojson.h"
 
 namespace extension {
 namespace bookmark {
 
-class BookmarkInstance : public common::Instance {
+struct BookmarkObject {
+  int id;
+  bp_bookmark_info_fmt bookmark_info;
+};
+
+struct Context {
+  int id;
+  int shouldGetItems;
+  std::vector<BookmarkObject> folders;
+};
+
+class BookmarkInstance : public common::ParsedInstance {
  public:
   BookmarkInstance();
   virtual ~BookmarkInstance();
 
  private:
-  virtual void HandleMessage(const char* msg);
-  virtual void HandleSyncMessage(const char* msg);
-
-  void HandleGet(const picojson::value& arg, picojson::value::object& o);
-  void HandleAdd(const picojson::value& arg, picojson::value::object& o);
-  void HandleRemove(const picojson::value& arg, picojson::value::object& o);
+  bool bookmark_foreach(Context& ctx, bp_bookmark_info_fmt& info);
+  void Bookmark_get(const picojson::value& arg, picojson::object& o);
+  void Bookmark_add(const picojson::value& arg, picojson::object& o);
+  void Bookmark_remove(const picojson::value& arg, picojson::object& o);
+  void Bookmark_removeAll(const picojson::value& msg, picojson::object& o);
+  void Bookmark_getRootId(const picojson::value& msg, picojson::object& o);
 };
-
-} // namespace bookmark
-} // namespace extension
-
+}  // namespace bookmark
+}  // namespace extension
 #endif  // BOOKMARK_BOOKMARK_INSTANCE_H_