[MessagePort] Add initial version of message port implementation
authorJin-Woo Jeong <jinw.jeong@samsung.com>
Thu, 22 Jan 2015 23:21:20 +0000 (08:21 +0900)
committerJin-Woo Jeong <jinw.jeong@samsung.com>
Thu, 22 Jan 2015 23:22:09 +0000 (08:22 +0900)
[Verification] Tested with SDK sample application.

Change-Id: I2373803c70edab07a7e50f182236ecaa436d79a1

packaging/webapi-plugins.spec
src/messageport/messageport.gyp
src/messageport/messageport_api.js
src/messageport/messageport_extension.cc
src/messageport/messageport_extension.h
src/messageport/messageport_instance.cc
src/messageport/messageport_instance.h

index 68dd18c8cafeff01e96d5872dd5964673a748791..38aabca24912da04745a69d6982b4a38f5496250 100644 (file)
@@ -154,7 +154,7 @@ BuildRequires: pkgconfig(evas)
 BuildRequires: pkgconfig(gio-2.0)
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(libudev)
-BuildRequires: pkgconfig(message-port)
+BuildRequires: pkgconfig(capi-message-port)
 BuildRequires: pkgconfig(minizip)
 BuildRequires: pkgconfig(zlib)
 BuildRequires: pkgconfig(msg-service)
@@ -182,6 +182,7 @@ BuildRequires: pkgconfig(capi-appfw-app-manager)
 BuildRequires: pkgconfig(capi-appfw-package-manager)
 BuildRequires: pkgconfig(wrt-plugins-ipc-message)
 
+
 %if 0%{?tizen_feature_power_support}
 BuildRequires: pkgconfig(capi-system-power)
 %endif
index 68416d70826d0363d9f7dd4669c4ed22fcc032f3..e8f8e1e1f6767e14631955ac5902864a26be87de 100644 (file)
@@ -6,12 +6,6 @@
     {
       'target_name': 'tizen_messageport',
       'type': 'loadable_module',
-      'variables': {
-        'packages': [
-          'bundle',
-          'message-port',
-        ],
-      },
       'sources': [
         'messageport_api.js',
         'messageport_extension.cc',
         'messageport_instance.cc',
         'messageport_instance.h',
       ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'vconf',
+              'capi-message-port',
+              'dlog'
+            ]
+          },
+        }],
+      ],
     },
   ],
 }
index cadafdddd9f695e46f573902c97eb7950d0bb18d..fb9d2ed20f99ceeb2303650dc54de00f6cdc30de 100644 (file)
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+// MessagePort
 
-function isInteger(value) {
-  return isFinite(value) && !isNaN(parseInt(value));
-}
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
 
-function isString(value) {
-  return typeof(value) === 'string' || value instanceof String;
-}
 
-function assertThrow(expr, exception) {
-  if (!expr)
-    throw new tizen.WebAPIException(tizen.WebAPIException[exception]);
-}
+var callbackId = 0;
+var callbacks = {};
 
-function sendSyncMessage(cmd, msg) {
-  msg['cmd'] = cmd;
+extension.setMessageListener(function(json) {
+  var msg = JSON.parse(json);
+  var listeners = callbacks[msg['local_port_id']];
 
-  var serialized = JSON.stringify(msg);
-  return JSON.parse(extension.internal.sendSyncMessage(serialized));
-}
+  console.log('Listeners length:' + listeners.length);
+  var rmp = new RemoteMessagePort(msg.remotePort, msg.remoteAppId, msg.trusted);
 
-function NativeBridge() {
-  this.listeners = {};
-  this.next_listener_id = 0;
-  this.queued_messages = {};
-}
+  for (var i = 0; i < listeners.length; i++) {
 
-NativeBridge.prototype.requestLocalMessagePort = function(messagePortName) {
-  return sendSyncMessage('RequestLocalMessagePort', {
-    messagePortName: messagePortName,
-    trusted: false
-  });
-};
+    var func = listeners[i][0];
+    func(msg.message, rmp);
+  }
 
-NativeBridge.prototype.requestTrustedLocalMessagePort = function(messagePortName) {
-  return sendSyncMessage('RequestLocalMessagePort', {
-    messagePortName: messagePortName,
-    trusted: true
-  });
-};
+});
 
-NativeBridge.prototype.requestRemoteMessagePort = function(appId, messagePortName) {
-  return sendSyncMessage('RequestRemoteMessagePort', {
-    appId: appId,
-    messagePortName: messagePortName,
-    trusted: false
-  });
-};
+function nextCallbackId() {
+  return callbackId++;
+}
 
-NativeBridge.prototype.requestTrustedRemoteMessagePort = function(appId, messagePortName) {
-  return sendSyncMessage('RequestRemoteMessagePort', {
-    appId: appId,
-    messagePortName: messagePortName,
-    trusted: true
-  });
+var ExceptionMap = {
+  'UnknownError' : tizen.WebAPIException.UNKNOWN_ERR,
+  'TypeMismatchError' : tizen.WebAPIException.TYPE_MISMATCH_ERR,
+  'InvalidValuesError' : tizen.WebAPIException.INVALID_VALUES_ERR,
+  'IOError' : tizen.WebAPIException.IO_ERR,
+  'ServiceNotAvailableError' : tizen.WebAPIException.SERVICE_NOT_AVAILABLE_ERR,
+  'SecurityError' : tizen.WebAPIException.SECURITY_ERR,
+  'NetworkError' : tizen.WebAPIException.NETWORK_ERR,
+  'NotSupportedError' : tizen.WebAPIException.NOT_SUPPORTED_ERR,
+  'NotFoundError' : tizen.WebAPIException.NOT_FOUND_ERR,
+  'InvalidAccessError' : tizen.WebAPIException.INVALID_ACCESS_ERR,
+  'AbortError' : tizen.WebAPIException.ABORT_ERR,
+  'QuotaExceededError' : tizen.WebAPIException.QUOTA_EXCEEDED_ERR
 };
 
-NativeBridge.prototype.addLocalListener = function(localPort, listenerFunc) {
-  if (!this.listeners.hasOwnProperty(localPort._id))
-    this.listeners[localPort._id] = [];
-
-  this.next_listener_id++;
-  this.listeners[localPort._id].push([listenerFunc, this.next_listener_id]);
+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(this.queued_messages[localPort.id]) !== 'undefined') {
-    var queue = this.queued_messages[localPort.id];
-    for (var i = 0, j = queue.length; i < j; i++)
-      this.onLocalMessageReceived(queue[i]);
-    this.queued_messages[localPort.id] = [];
+  if (typeof result !== 'object') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
   }
 
-  return this.next_listener_id;
-};
+  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 tizen.WebAPIException(ExceptionMap[err.name], err.message);
+      } else {
+        throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR, err.message);
+      }
+    }
+    return false;
+  }
+}
 
-NativeBridge.prototype.removeLocalListener = function(localPort, watchId) {
-  var listeners = this.listeners[localPort._id];
-  if (typeof(listeners) === 'undefined')
-    return { not_found: 1 };
 
-  var to_delete = [];
-  for (var i = 0, j = listeners.length; i < j; i++) {
-    var listener_id = listeners[i][1];
-    if (watchId == listener_id)
-      to_delete.push(i);
+function callNativeWithCallback(cmd, args, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    args['callbackId'] = id;
+    callbacks[id] = callback;
   }
 
-  if (to_delete.length == 0)
-    return { not_found: 1 };
+  return callNative(cmd, args);
+}
 
-  for (var i = 0, j = to_delete.length; i < j; i++)
-    this.listeners.splice(to_delete[i], 1);
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
 
-  return {};
-};
 
-NativeBridge.prototype.onLocalMessageReceived = function(msg) {
-  var listeners = this.listeners[msg.id];
-  if (typeof(listeners) === 'undefined') {
-    if (typeof(this.queued_messages[msg.id]) === 'undefined')
-      this.queued_messages[msg.id] = [];
-    this.queued_messages[msg.id].push(msg);
-    return;
-  }
+function MessagePortManager() {
+  // constructor of MessagePortManager
+}
 
-  // FIXME(leandro): Reuse RemoteMessagePort if it has been requested
-  // previously.
-  var rmp = new RemoteMessagePort(msg.remotePort, msg.remoteAppId, msg.trusted);
-  for (var i = 0; i < listeners.length; i++) {
-    var func = listeners[i][0];
-    func(msg.data, rmp);
-  }
-};
 
-NativeBridge.prototype.sendMessage = function(remotePort, data, localPort) {
-  return sendSyncMessage('SendMessage', {
-    appId: remotePort.appId,
-    messagePortName: remotePort.messagePortName,
-    data: data,
-    trusted: remotePort.isTrusted,
-    localPort: localPort ? localPort._id : -1
-  });
-};
+MessagePortManager.prototype.requestLocalMessagePort = function(localMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'localMessagePortName', 'type': types_.STRING}
+  ]);
+
+  var nativeParam = {
+    'localMessagePortName': args.localMessagePortName
+  };
 
-NativeBridge.prototype.toTizenException = function(nativeError) {
-  function isUndefined(v) {
-    return typeof(v) === 'undefined';
+  try {
+
+    var localPortId = callNative('MessagePortManager_requestLocalMessagePort', nativeParam);
+
+  } catch (e) {
+    throw e;
   }
 
-  assertThrow(isUndefined(nativeError.not_found), 'NOT_FOUND_ERR');
-  assertThrow(isUndefined(nativeError.invalid_parameter), 'INVALID_VALUES_ERR');
-  assertThrow(isUndefined(nativeError.certificate_error), 'INVALID_ACCESS_ERR');
-  assertThrow(isUndefined(nativeError.max_exceeded), 'QUOTA_EXCEEDED_ERR');
-  assertThrow(nativeError.success === true, 'UNKNOWN_ERR');
-};
+  var returnObject = new LocalMessagePort(localPortId, args.localMessagePortName, false);
 
-var nativeBridge = new NativeBridge();
+  return returnObject;
+};
 
-extension.setMessageListener(function(json) {
-  var msg = JSON.parse(json);
+MessagePortManager.prototype.requestTrustedLocalMessagePort = function(localMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'localMessagePortName', 'type': types_.STRING}
+  ]);
 
-  if (msg.cmd == 'LocalMessageReceived')
-    nativeBridge.onLocalMessageReceived(msg);
-  else
-    console.error('Unknown command received: ' + msg.cmd);
-});
+  var nativeParam = {
+    'localMessagePortName': args.localMessagePortName
+  };
 
+  try {
 
-function MessagePortManager() {
-}
+    var localPortId = callNative('MessagePortManager_requestTrustedLocalMessagePort', nativeParam);
 
-MessagePortManager.prototype.requestLocalMessagePort = function(
-    localMessagePortName) {
-  assertThrow(isString(localMessagePortName), 'TYPE_MISMATCH_ERR');
+  } catch (e) {
+    throw e;
+  }
 
-  var messagePort = nativeBridge.requestLocalMessagePort(
-      localMessagePortName);
-  nativeBridge.toTizenException(messagePort);
+  var returnObject = new LocalMessagePort(localPortId, args.localMessagePortName, true);
 
-  return new LocalMessagePort(messagePort.id, localMessagePortName, false);
+  return returnObject;
 };
 
-MessagePortManager.prototype.requestTrustedLocalMessagePort = function(
-    localMessagePortName) {
-  assertThrow(isString(localMessagePortName), 'TYPE_MISMATCH_ERR');
+MessagePortManager.prototype.requestRemoteMessagePort = function(appId, remoteMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'appId', 'type': types_.STRING},
+    {'name' : 'remoteMessagePortName', 'type': types_.STRING}
+  ]);
 
-  var messagePort = nativeBridge.requestTrustedLocalMessagePort(
-      localMessagePortName);
-  nativeBridge.toTizenException(messagePort);
+  var nativeParam = {
+    'appId': args.appId,
+    'remoteMessagePortName': args.remoteMessagePortName
+  };
 
-  return new LocalMessagePort(messagePort.id, localMessagePortName, true);
-};
+  try {
 
-MessagePortManager.prototype.requestRemoteMessagePort = function(
-    appId, remoteMessagePortName) {
-  assertThrow(isString(appId), 'TYPE_MISMATCH_ERR');
-  assertThrow(isString(remoteMessagePortName), 'TYPE_MISMATCH_ERR');
+    var syncResult = callNative('MessagePortManager_requestRemoteMessagePort', nativeParam);
 
-  var messagePort = nativeBridge.requestRemoteMessagePort(
-      appId, remoteMessagePortName);
-  nativeBridge.toTizenException(messagePort);
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new RemoteMessagePort(args.remoteMessagePortName, args.appId, false);
 
-  return new RemoteMessagePort(remoteMessagePortName, appId, false);
+  return returnObject;
 };
 
-MessagePortManager.prototype.requestTrustedRemoteMessagePort = function(
-    appId, remoteMessagePortName) {
-  assertThrow(isString(appId), 'TYPE_MISMATCH_ERR');
-  assertThrow(isString(remoteMessagePortName), 'TYPE_MISMATCH_ERR');
+MessagePortManager.prototype.requestTrustedRemoteMessagePort =
+    function(appId, remoteMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'appId', 'type': types_.STRING},
+    {'name' : 'remoteMessagePortName', 'type': types_.STRING}
+  ]);
+
+  var nativeParam = {
+    'remoteMessagePortName': args.remoteMessagePortName
+  };
 
-  var messagePort = nativeBridge.requestTrustedRemoteMessagePort(appId,
-      remoteMessagePortName);
-  nativeBridge.toTizenException(messagePort);
+  try {
+
+    var syncResult = callNative('MessagePortManager_requestTrustedRemoteMessagePort', nativeParam);
 
-  return new RemoteMessagePort(remoteMessagePortName, appId, true);
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new RemoteMessagePort(args.remoteMessagePortName, args.appId, true);
+
+  return returnObject;
 };
 
+
 function LocalMessagePort(id, messagePortName, isTrusted) {
   Object.defineProperties(this, {
-    '_id': { value: id, writable: false, enumerable: false },
-    'messagePortName': { value: messagePortName, writable: false },
+    'id': { value: id, writable: false },
+    'messagePortName': { value: messagePortName, writable: false, enumerable: false },
     'isTrusted': { value: !!isTrusted, writable: false }
   });
 }
 
+
 LocalMessagePort.prototype.addMessagePortListener = function(listener) {
-  assertThrow(listener instanceof Function);
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'listener', 'type': types_.FUNCTION, 'nullable': false}
+  ]);
+
+  if (!callbacks.hasOwnProperty(this.id)) callbacks[this.id] = [];
+
+  callbackId++;
+  callbacks[this.id].push([listener, callbackId]);
+
+  return callbackId;
 
-  return nativeBridge.addLocalListener(this, listener);
 };
 
 LocalMessagePort.prototype.removeMessagePortListener = function(watchId) {
-  assertThrow(isInteger(watchId), 'TYPE_MISMATCH_ERR');
-  assertThrow(watchId >= 0, 'INVALID_VALUES_ERR');
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'watchId', 'type': types_.LONG }
+  ]);
+
+  if (args.watchId <= 0)
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'The input parameter contains an invalid value.');
+
+  var to_delete;
+  var listeners = callbacks[this.id];
+
+  for (var i = 0, j = listeners.length; i < j; i++) {
+    var listener_id = listeners[i][1];
+    if (watchId == listener_id) {
+      to_delete = i;
+      break;
+    }
+  }
+
+  if (typeof to_delete == 'undefined')
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
+        'The port of the target application is not found.');
+
+  listeners.splice(to_delete, 1);
 
-  var error = nativeBridge.removeLocalListener(this, watchId);
-  nativeBridge.toTizenException(error);
 };
 
+
 function RemoteMessagePort(messagePortName, appId, isTrusted) {
   Object.defineProperties(this, {
     'messagePortName': { value: messagePortName, writable: false },
@@ -227,31 +244,44 @@ function RemoteMessagePort(messagePortName, appId, isTrusted) {
   });
 }
 
-RemoteMessagePort.prototype.sendMessage = function(data, localMessagePort) {
-  assertThrow(data instanceof Array, 'TYPE_MISMATCH_ERR');
-  if (arguments.length >= 2)
-    assertThrow(localMessagePort instanceof LocalMessagePort, 'TYPE_MISMATCH_ERR');
+RemoteMessagePort.prototype.sendMessage = function(data) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'data', 'type': types_.ARRAY},
+    {'name' : 'localMessagePort', 'type': types_.PLATFORM_OBJECT, 'optional' : true,
+      'nullable' : true, 'values' : LocalMessagePort }
+  ]);
 
   var filtered_data = new Array(data.length);
+
+  for (var i = 0, j = data.length; i < j; i++) {
+    if (Object.hasOwnProperty(data[i], 'key'))
+      throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+          'The input parameter contains an invalid value.');
+    if (Object.hasOwnProperty(data[i], 'value'))
+      throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+          'The input parameter contains an invalid value.');
+    filtered_data[i] = { key: data[i].key, value: data[i].value };
+  }
+
+
+  var nativeParam = {
+    'appId': this.appId,
+    'messagePortName': this.messagePortName,
+    'data': filtered_data,
+    'trusted': this.isTrusted,
+    'local_port_id': args.localMessagePort ? args.localMessagePort.id : -1
+  };
+
   try {
-    for (var i = 0, j = data.length; i < j; i++)
-      filtered_data[i] = { key: data[i].key, value: data[i].value };
+    var syncResult = callNative('RemoteMessagePort_sendMessage', nativeParam);
+
   } catch (e) {
-    assertThrow(Object.hasOwnProperty(data[i], 'key'), 'INVALID_VALUES_ERR');
-    assertThrow(Object.hasOwnProperty(data[i], 'value'), 'INVALID_VALUES_ERR');
-    throw new tizen.WebAPIException.UNKNOWN_ERR;
+    throw e;
   }
 
-  var error = nativeBridge.sendMessage(this, filtered_data, localMessagePort);
-  nativeBridge.toTizenException(error);
 };
 
-var messagePortManagerObject = new MessagePortManager();
-exports.requestLocalMessagePort =
-    messagePortManagerObject.requestLocalMessagePort;
-exports.requestTrustedLocalMessagePort =
-    messagePortManagerObject.requestTrustedLocalMessagePort;
-exports.requestRemoteMessagePort =
-    messagePortManagerObject.requestRemoteMessagePort;
-exports.requestTrustedRemoteMessagePort =
-    messagePortManagerObject.requestTrustedRemoteMessagePort;
+
+
+exports = new MessagePortManager();
+
index 5a4925a995cce0143a2cc18b7a2f024fd81f5d90..6894abf0d61e5b7ab6b95283e7c38107895f3fb8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright 2014 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.
 
@@ -6,18 +6,20 @@
 
 #include "messageport/messageport_instance.h"
 
+// This will be generated from messageport_api.js
+extern const char kSource_messageport_api[];
+
 common::Extension* CreateExtension() {
   return new MessageportExtension;
 }
 
-// This will be generated from messageport_api.js.
-extern const char kSource_messageport_api[];
-
 MessageportExtension::MessageportExtension() {
   SetExtensionName("tizen.messageport");
   SetJavaScriptAPI(kSource_messageport_api);
 }
 
+MessageportExtension::~MessageportExtension() {}
+
 common::Instance* MessageportExtension::CreateInstance() {
-  return new MessageportInstance();
+  return new extension::messageport::MessageportInstance;
 }
index 418e69f0382209c374eae6de63c1b499a947d327..8daa4feab79ec73fed98131ff0ff8a4720f23660 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright 2014 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.
 
@@ -10,8 +10,9 @@
 class MessageportExtension : public common::Extension {
  public:
   MessageportExtension();
+  virtual ~MessageportExtension();
+
  private:
-  // common::Extension implementation.
   virtual common::Instance* CreateInstance();
 };
 
index 801d75ceee6fae0944a6835f0524dff67665320f..5a65451f29886c762ae585443b111b5d9e08b6df 100644 (file)
@@ -1,51 +1,58 @@
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright 2014 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 "messageport/messageport_instance.h"
 
-#include <message-port.h>
-#include <string.h>
-
-#include <map>
-#include <string>
+#include <functional>
 #include <vector>
+#include <string>
 
-MessageportInstance::MessageportIdToInstanceMap
-      MessageportInstance::mp_id_to_instance_map_;
-
-namespace {
-
-bool ErrorIfMessageHasNoKey(const picojson::value& msg,
-      const std::string& key, picojson::value::object& reply) {
-  if (!msg.contains(key)) {
-    std::cerr << "Required parameter \"" << key << "\" missing from message\n";
-
-    reply["invalid_parameter"] = picojson::value(true);
-    return true;
-  }
-
-  return false;
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace messageport {
+
+using common::TypeMismatchException;
+using common::InvalidValuesException;
+using common::UnknownException;
+using common::NotFoundException;
+using common::QuotaExceededException;
+
+MessageportInstance::MessageportInstance() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+  #define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&MessageportInstance::x, this, _1, _2));
+  REGISTER_SYNC("MessagePortManager_requestTrustedRemoteMessagePort",
+                MessagePortManagerRequesttrustedremotemessageport);
+  REGISTER_SYNC("MessagePortManager_requestLocalMessagePort",
+                MessagePortManagerRequestlocalmessageport);
+  REGISTER_SYNC("MessagePortManager_requestTrustedLocalMessagePort",
+                MessagePortManagerRequesttrustedlocalmessageport);
+  REGISTER_SYNC("MessagePortManager_requestRemoteMessagePort",
+                MessagePortManagerRequestremotemessageport);
+  REGISTER_SYNC("RemoteMessagePort_sendMessage", RemoteMessagePortSendmessage);
+  #undef REGISTER_SYNC
 }
 
-};  // namespace
-
-void MessageportInstance::RegisterLocalMessageport(int mp_id,
-      MessageportInstance *instance) {
-  MessageportInstance::mp_id_to_instance_map_[mp_id] = instance;
+MessageportInstance::~MessageportInstance() {
 }
 
-MessageportInstance* MessageportInstance::GetInstanceByPortId(int mp_id) {
-  MessageportIdToInstanceMap::iterator it =
-        MessageportInstance::mp_id_to_instance_map_.find(mp_id);
 
-  if (it == mp_id_to_instance_map_.end())
-    return 0;
-  return it->second;
-}
+enum MessageportCallbacks {
+  MessagePortManagerRequesttrustedremotemessageportCallback,
+  MessagePortManagerRequestlocalmessageportCallback,
+  MessagePortManagerRequesttrustedlocalmessageportCallback,
+  MessagePortManagerRequestremotemessageportCallback,
+  LocalMessagePortRemovemessageportlistenerCallback,
+  RemoteMessagePortSendmessageCallback,
+  LocalMessagePortAddmessageportlistenerCallback
+};
 
-void MessageportInstance::BundleJsonIterator(
-      const char *k, const char *v, void *d) {
+static void BundleJsonIterator(const char *k, const char *v, void *d) {
   picojson::value::array *array = static_cast<picojson::value::array *>(d);
   picojson::value::object o;
   o["key"] = picojson::value(k);
@@ -53,229 +60,256 @@ void MessageportInstance::BundleJsonIterator(
   array->push_back(picojson::value(o));
 }
 
-void MessageportInstance::OnReceiveLocalMessage(
-      int id, const char* remote_app_id, const char* remote_port,
-      bool trusted_message, bundle* data) {
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+static void OnReceiveLocalMessage(int local_port_id,
+  const char* remote_app_id, const char* remote_port,
+  bool trusted_remote_port, bundle* message, void* user_data) {
+  MessageportInstance* object = static_cast<MessageportInstance*>(user_data);
   picojson::value::object o;
+  picojson::value::array data;
 
-  o["cmd"] = picojson::value("LocalMessageReceived");
-  o["id"] = picojson::value(static_cast<double>(id));
+  o["local_port_id"] = picojson::value(static_cast<double>(local_port_id));
   o["remoteAppId"] = picojson::value(remote_app_id);
   o["remotePort"] = picojson::value(remote_port);
-  o["trusted"] = picojson::value(trusted_message);
+  o["trusted_remote_port"] = picojson::value(trusted_remote_port);
+
+  LoggerD("Msg received from: %s", remote_app_id);
 
-  picojson::value::array d;
-  bundle_iterate(data, BundleJsonIterator, &d);
+  bundle_iterate(message, BundleJsonIterator, &data);
 
-  o["data"] = picojson::value(d);
+  o["message"] = picojson::value(data);
 
-  PostMessage(picojson::value(o).serialize().c_str());
+  object->PostMessage(picojson::value(o).serialize().c_str());
 }
 
-void MessageportInstance::OnReceiveLocalMessageThunk(
-      int id, const char* remote_app_id, const char* remote_port,
-      bool trusted_message, bundle* data) {
-  MessageportInstance* self = MessageportInstance::GetInstanceByPortId(id);
-  if (!self) {
-    std::cerr << "Could not find Messageport by id: " << id << "\n";
-    return;
-  }
 
-  self->OnReceiveLocalMessage(id, remote_app_id, remote_port, trusted_message,
-        data);
-}
+void MessageportInstance::MessagePortManagerRequestlocalmessageport
+  (const picojson::value& args, picojson::object& out) {
+  CHECK_EXIST(args, "localMessagePortName", out)
 
-void MessageportInstance::HandleSyncMessage(const char *message) {
-  picojson::value v;
+  int portId;
+  const std::string& localMessagePortName =
+    args.get("localMessagePortName").get<std::string>();
 
-  std::string err;
-  picojson::parse(v, message, message + strlen(message), &err);
-  if (!err.empty()) {
-    std::cerr << "Ignoring unparsable sync message: " << message << "\n";
-    std::cerr << "Error was: " << err << "\n";
-    return;
-  }
+  portId = message_port_register_local_port
+    (localMessagePortName.c_str(), OnReceiveLocalMessage, this);
+
+  LoggerD("Registering local port %s : %s", localMessagePortName.c_str(),
+    portId < 0 ? "false" : "true");
 
-  picojson::value::object o;
-  if (!ErrorIfMessageHasNoKey(v, "cmd", o)) {
-    std::string cmd = v.get("cmd").to_str();
-
-    if (cmd == "RequestLocalMessagePort") {
-      HandleRequestLocalMessagePort(v, o);
-    } else if (cmd == "RequestRemoteMessagePort") {
-      HandleRequestRemoteMessagePort(v, o);
-    } else if (cmd == "SendMessage") {
-      HandleSendMessage(v, o);
-    } else {
-      std::cerr << "Ignoring unknown command: " << cmd << "\n";
-      return;
-    }
-  } else {
-    std::cerr << "Message has no command, ignoring\n";
-    return;
-  }
 
-  SendSyncReply(picojson::value(o).serialize().c_str());
+  if(portId < 0){
+    
+    switch (portId) {
+      case MESSAGE_PORT_ERROR_INVALID_PARAMETER:
+        ReportError(InvalidValuesException
+          ("The input parameter contains an invalid value."),out);
+        break;
+      case MESSAGE_PORT_ERROR_OUT_OF_MEMORY:
+        ReportError(UnknownException("Out of memory."),out);
+        break;
+      case MESSAGE_PORT_ERROR_IO_ERROR:
+        ReportError(UnknownException("Internal I/O error ocurred."),out);
+        break;      
+      default:
+        ReportError(UnknownException("Unknown Exception"),out);
+        break;
+      }
+  }
+  else
+    ReportSuccess(picojson::value(static_cast<double>(portId)), out);
 }
 
-void MessageportInstance::HandleRequestLocalMessagePort(
-        const picojson::value& msg, picojson::value::object& o) {
-  if (ErrorIfMessageHasNoKey(msg, "messagePortName", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "trusted", o))
-    return;
+void MessageportInstance::
+  MessagePortManagerRequesttrustedlocalmessageport
+    (const picojson::value& args, picojson::object& out) {
+  CHECK_EXIST(args, "localMessagePortName", out)
 
-  std::string message_port_name = msg.get("messagePortName").to_str();
-  int mp_id;
+  int portId;
+  const std::string& localMessagePortName =
+    args.get("localMessagePortName").get<std::string>();
 
-  if (msg.get("trusted").get<bool>()) {
-    mp_id = messageport_register_trusted_local_port(message_port_name.c_str(),
-          OnReceiveLocalMessageThunk);
-  } else {
-    mp_id = messageport_register_local_port(message_port_name.c_str(),
-          OnReceiveLocalMessageThunk);
-  }
+  portId = message_port_register_trusted_local_port
+    (localMessagePortName.c_str(), OnReceiveLocalMessage, NULL);
 
-  if (mp_id < 0) {
-    switch (mp_id) {
-      case MESSAGEPORT_ERROR_INVALID_PARAMETER:
-        o["invalid_parameter"] = picojson::value(true);
-        break;
-      case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
-        o["out_of_memory"] = picojson::value(true);
+  LoggerD("Registering trusted local port %s:%s", localMessagePortName.c_str(),
+    portId < 0 ? "false" : "true");
+
+  if(portId < 0){
+    
+    switch (portId) {
+      case MESSAGE_PORT_ERROR_INVALID_PARAMETER:
+        ReportError(InvalidValuesException
+          ("The input parameter contains an invalid value."),out);
         break;
-      case MESSAGEPORT_ERROR_IO_ERROR:
-        o["io_error"] = picojson::value(true);
+      case MESSAGE_PORT_ERROR_OUT_OF_MEMORY:
+        ReportError(UnknownException("Out of memory."),out);
         break;
+      case MESSAGE_PORT_ERROR_IO_ERROR:
+        ReportError(UnknownException("Internal I/O error ocurred."),out);
+        break;      
       default:
-        o["unknown_error"] = picojson::value(true);
-    }
-  } else {
-    MessageportInstance::RegisterLocalMessageport(mp_id, this);
-    o["id"] = picojson::value(static_cast<double>(mp_id));
-    o["success"] = picojson::value(true);
+        ReportError(UnknownException("Unknown Exception"),out);
+        break;
+      }
   }
+  else
+    ReportSuccess(picojson::value(static_cast<double>(portId)), out);
+
 }
 
-void MessageportInstance::HandleRequestRemoteMessagePort(
-      const picojson::value& msg, picojson::value::object& o) {
-  if (ErrorIfMessageHasNoKey(msg, "messagePortName", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "trusted", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "appId", o))
-    return;
-
-  std::string message_port_name = msg.get("messagePortName").to_str();
-  std::string app_id = msg.get("appId").to_str();
-  int ret_val;
-  bool exist;
-
-  if (msg.get("trusted").get<bool>()) {
-    ret_val = messageport_check_trusted_remote_port(app_id.c_str(),
-          message_port_name.c_str(), &exist);
-  } else {
-    ret_val = messageport_check_remote_port(app_id.c_str(),
-          message_port_name.c_str(), &exist);
-  }
+void MessageportInstance::
+  MessagePortManagerRequestremotemessageport
+    (const picojson::value& args, picojson::object& out) {
+  CHECK_EXIST(args, "remoteMessagePortName", out)
+
+  const std::string& remoteMessagePortName =
+    args.get("remoteMessagePortName").get<std::string>();
+  const std::string& appId = args.get("appId").get<std::string>();
+
+  int ret;
+  bool portCheck;
 
-  if (!exist) {
-    o["not_found"] = picojson::value(true);
-    return;
+  ret = message_port_check_remote_port(appId.c_str(),
+    remoteMessagePortName.c_str(), &portCheck);
+
+  LoggerD("Checking remote port of %s: %s", remoteMessagePortName.c_str(),
+    portCheck ? "true" : "false");
+
+  if(ret == MESSAGE_PORT_ERROR_NONE){
+    if (portCheck) ReportSuccess(out);
+    else
+      ReportError(NotFoundException
+        ("The port of the target application is not found"), out);
   }
+  else if(ret == MESSAGE_PORT_ERROR_INVALID_PARAMETER)
+      ReportError(InvalidValuesException
+        ("An input parameter contains an invalid value."),out);
+  else if(ret == MESSAGE_PORT_ERROR_OUT_OF_MEMORY)
+      ReportError(UnknownException("Out of memory."), out);
+  else if(ret == MESSAGE_PORT_ERROR_IO_ERROR)
+      ReportError(UnknownException("Internal I/O error ocurred."),out);
+  else 
+      ReportError(UnknownException("Unknown Error"),out);
+    
+}
 
-  if (ret_val < 0) {
-    switch (ret_val) {
-      case MESSAGEPORT_ERROR_INVALID_PARAMETER:
-        o["invalid_parameter"] = picojson::value(true);
-        break;
-      case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
-        o["out_of_memory"] = picojson::value(true);
-        break;
-      case MESSAGEPORT_ERROR_IO_ERROR:
-        o["io_error"] = picojson::value(true);
-        break;
-      case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
-        o["certificate_error"] = picojson::value(true);
-        break;
-      default:
-        o["unknown_error"] = picojson::value(true);
+void MessageportInstance::
+  MessagePortManagerRequesttrustedremotemessageport
+    (const picojson::value& args, picojson::object& out) {
+  CHECK_EXIST(args, "remoteMessagePortName", out)
+
+  const std::string& remoteMessagePortName =
+    args.get("remoteMessagePortName").get<std::string>();
+  const std::string& appId = args.get("appId").get<std::string>();
+
+  bool portCheck;
+  int ret;
+
+  ret = message_port_check_trusted_remote_port
+        (appId.c_str(), remoteMessagePortName.c_str(), &portCheck);
+
+  LoggerD("Checking trusted remoteport of %s:%s",
+    remoteMessagePortName.c_str(), portCheck ? "true":"false");
+
+
+    if(ret == MESSAGE_PORT_ERROR_NONE){
+      if (portCheck) ReportSuccess(out);
+      else
+        ReportError(NotFoundException
+          ("The port of the target application is not found"), out);
     }
-  } else {
-    o["success"] = picojson::value(true);
-  }
+    else if(ret == MESSAGE_PORT_ERROR_INVALID_PARAMETER)
+        ReportError(InvalidValuesException
+          ("An input parameter contains an invalid value."),out);
+    else if(ret == MESSAGE_PORT_ERROR_OUT_OF_MEMORY)
+        ReportError(UnknownException("Out of memory."), out);
+    else if(ret == MESSAGE_PORT_ERROR_IO_ERROR)
+        ReportError(UnknownException("Internal I/O error ocurred."),out);
+    else if(ret == MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH)
+        ReportError(UnknownException(
+        "The remote application is not signed with the same certificate"),out);
+    else 
+        ReportError(UnknownException("Unknown Error"),out);
+
 }
 
-void MessageportInstance::HandleSendMessage(
-      const picojson::value& msg, picojson::value::object& o) {
-  if (ErrorIfMessageHasNoKey(msg, "messagePortName", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "trusted", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "appId", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "localPort", o))
-    return;
-  if (ErrorIfMessageHasNoKey(msg, "data", o))
-    return;
-
-  std::string app_id = msg.get("appId").to_str();
-  std::string message_port_name = msg.get("messagePortName").to_str();
-  int local_port = static_cast<int>(msg.get("localPort").get<double>());
-  std::vector<picojson::value> data = msg.get("data").get<picojson::array>();
-  int ret_val;
+void MessageportInstance::RemoteMessagePortSendmessage
+  (const picojson::value& args, picojson::object& out) {
+  const std::string& appId = args.get("appId").get<std::string>();
+  const std::string& message_port_name =
+    args.get("messagePortName").get<std::string>();
+  std::vector<picojson::value> data = args.get("data").get<picojson::array>();
+
+  long local_port_id =
+    static_cast<long>(args.get("local_port_id").get<double>());
+  bool trusted = args.get("trusted").get<bool>();
+
+  int result;
+
   bundle* bundle = bundle_create();
 
   for (picojson::value::array::iterator it = data.begin();
-          it != data.end(); it++) {
-    bundle_add(bundle, (*it).get("key").to_str().c_str(),
-          (*it).get("value").to_str().c_str());
+       it != data.end(); it++) {
+      bundle_add(bundle, (*it).get("key").to_str().c_str(),
+        (*it).get("value").to_str().c_str());
   }
 
-  if (msg.get("trusted").get<bool>()) {
-    if (local_port < 0) {
-      ret_val = messageport_send_trusted_message(app_id.c_str(),
-            message_port_name.c_str(), bundle);
-    } else {
-      ret_val = messageport_send_bidirectional_trusted_message(local_port,
-            app_id.c_str(), message_port_name.c_str(), bundle);
-    }
+  LoggerD("%s to %s", trusted ?
+    "Sending trusted messages" : "Sending normal messages",
+    message_port_name.c_str());
+
+  if (trusted) {
+    if (local_port_id < 0) {
+          result = message_port_send_trusted_message
+            (appId.c_str(), message_port_name.c_str(), bundle);
+        } else {
+          result = message_port_send_trusted_message_with_local_port
+            (appId.c_str(), message_port_name.c_str(), bundle, local_port_id);
+        }
   } else {
-    if (local_port < 0) {
-      ret_val = messageport_send_message(app_id.c_str(),
-            message_port_name.c_str(), bundle);
+    if (local_port_id < 0) {
+      result = message_port_send_message
+        (appId.c_str(), message_port_name.c_str(), bundle);
     } else {
-      ret_val = messageport_send_bidirectional_message(local_port,
-            app_id.c_str(), message_port_name.c_str(), bundle);
+      result = message_port_send_message_with_local_port
+        (appId.c_str(), message_port_name.c_str(), bundle, local_port_id);
     }
   }
 
   bundle_free(bundle);
 
-  if (ret_val < 0) {
-    switch (ret_val) {
-      case MESSAGEPORT_ERROR_INVALID_PARAMETER:
-        o["invalid_parameter"] = picojson::value(true);
-        return;
-      case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
-        o["out_of_memory"] = picojson::value(true);
-        return;
-      case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
-        o["messageport_not_found"] = picojson::value(true);
-        return;
-      case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
-        o["certificate_not_found"] = picojson::value(true);
-        return;
-      case MESSAGEPORT_ERROR_MAX_EXCEEDED:
-        o["max_exceeded"] = picojson::value(true);
-        return;
-      case MESSAGEPORT_ERROR_IO_ERROR:
-        o["io_error"] = picojson::value(true);
-        return;
-      default:
-        o["unknown_error"] = picojson::value(true);
-    }
-  } else {
-    o["success"] = picojson::value(true);
-  }
+  if(result == MESSAGE_PORT_ERROR_NONE)
+    ReportSuccess(out);
+  else if(result == MESSAGE_PORT_ERROR_INVALID_PARAMETER)
+    ReportError(InvalidValuesException
+      ("An input parameter contains an invalid value."),out);
+  else if(result == MESSAGE_PORT_ERROR_PORT_NOT_FOUND)
+    ReportError(NotFoundException
+      ("The port of the target application is not found"),out);
+  else if(result == MESSAGE_PORT_ERROR_MAX_EXCEEDED)
+    ReportError(QuotaExceededException
+      ("The size of message has exceeded the maximum limit."),out);
+  else if(result == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE)
+    ReportError(UnknownException("A resource is temporarily unavailable."),out);
+  else if(result == MESSAGE_PORT_ERROR_OUT_OF_MEMORY)
+    ReportError(UnknownException("Out of memory."),out);
+  else if(result == MESSAGE_PORT_ERROR_IO_ERROR)
+    ReportError(UnknownException("Internal I/O error ocurred."),out);
+  else if(result == MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH)
+    ReportError(UnknownException
+      ("The remote application is not signed with the same certificate"),out);
+  else ReportError(UnknownException("Unknown Exception"),out);
+  
 }
+
+
+#undef CHECK_EXIST
+
+}  // namespace messageport
+}  // namespace extension
index ea42f194cce1cec1443ab22d91ebe4b7abdfce95..cb9fd5e20d4e68484bfd60c5dc895546790a63f6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright 2014 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.
 
@@ -6,43 +6,32 @@
 #define MESSAGEPORT_MESSAGEPORT_INSTANCE_H_
 
 #include <bundle.h>
-
-#include <map>
+#include <message_port.h>
 
 #include "common/extension.h"
-#include "common/picojson.h"
 
-class MessageportInstance : public common::Instance {
+namespace extension {
+namespace messageport {
+
+class MessageportInstance : public common::ParsedInstance {
+ public:
+  MessageportInstance();
+  virtual ~MessageportInstance();
+
  private:
-  // common::Instance implementation.
-  virtual void HandleMessage(const char*) {}
-  virtual void HandleSyncMessage(const char* msg);
-
-  // Command handlers.
-  void HandleRequestLocalMessagePort(const picojson::value& msg,
-          picojson::value::object& reply);
-  void HandleRequestRemoteMessagePort(const picojson::value& msg,
-          picojson::value::object& reply);
-  void HandleSendMessage(const picojson::value& msg,
-          picojson::value::object& reply);
-
-  // Messageport ID <-> MessageportInstance mapping.
-  typedef std::map<int, MessageportInstance *> MessageportIdToInstanceMap;
-  static MessageportIdToInstanceMap mp_id_to_instance_map_;
-
-  static void RegisterLocalMessageport(int mp_id,
-        MessageportInstance *instance);
-  static MessageportInstance* GetInstanceByPortId(int mp_id);
-
-  // bundle_iterate() callback.
-  static void BundleJsonIterator(const char *key, const char *value,
-        void *data);
-
-  // messageport_register[_trusted]_local_port() implementation.
-  void OnReceiveLocalMessage(int id, const char* remote_app_id,
-        const char* remote_port, bool trusted_message, bundle* data);
-  static void OnReceiveLocalMessageThunk(int id, const char* remote_app_id,
-        const char* remote_port, bool trusted_message, bundle* data);
+  void MessagePortManagerRequestlocalmessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequesttrustedlocalmessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequestremotemessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequesttrustedremotemessageport
+    (const picojson::value& args, picojson::object& out);
+  void RemoteMessagePortSendmessage
+    (const picojson::value& args, picojson::object& out);
 };
 
+}  // namespace messageport
+}  // namespace extension
+
 #endif  // MESSAGEPORT_MESSAGEPORT_INSTANCE_H_