%define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
Name: webapi-plugins
-Version: 1.23
+Version: 1.27
Release: 0
License: Apache-2.0 and BSD-2.0 and MIT
Group: Development/Libraries
%define tizen_feature_tvinputdevice_support 0
+%if 0%{?tizen_is_emulator}
+%define tizen_feature_convergence_support 0
+%else
+%define tizen_feature_convergence_support 1
+%endif
+
%endif # tizen_profile_mobile
####################################################################
%define tizen_feature_message_port_support 1
%define tizen_feature_messaging_support 0
%define tizen_feature_nfc_emulation_support 0
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_nfc_support 0
-%else
%define tizen_feature_nfc_support 1
-%endif
%define tizen_feature_notification_support 1
%define tizen_feature_package_support 1
%define tizen_feature_power_support 1
%define tizen_feature_nbs_support 0
%endif
+%if 0%{?tizen_is_emulator}
+%define tizen_feature_convergence_support 0
+%else
+%define tizen_feature_convergence_support 1
+%endif
+
%endif # tizen_profile_wearable
####################################################################
%define tizen_feature_wi_fi_support 1
%define tizen_feature_inputdevice_support 0
%define tizen_feature_tvinputdevice_support 1
+%define tizen_feature_convergence_support 1
%endif # tizen_profile_tv
%endif
%if 0%{?tizen_feature_se_support}
-BuildRequires: pkgconfig(smartcard-service)
-BuildRequires: pkgconfig(smartcard-service-common)
+BuildRequires: pkgconfig(capi-network-smartcard)
%endif
%if 0%{?tizen_feature_message_port_support}
BuildRequires: pkgconfig(capi-system-media-key)
%endif
+%if 0%{?tizen_feature_convergence_support}
+BuildRequires: pkgconfig(d2d-conv-manager)
+%endif
+
%if 0%{?tizen_feature_widget_service_support}
BuildRequires: pkgconfig(widget_service)
%endif
GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_feature_widget_service_support}"
GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_feature_wi_fi_support}"
GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_feature_tvinputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_convergence_support=%{?tizen_feature_convergence_support}"
./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
//class BluetoothLEDevice ////////////////////////////////////////////////////
var BluetoothLEDevice = function(data) {
var address = "", name = null, txpowerlevel = null, appearance = null, uuids = null,
- solicitationuuids = null, serviceData = null, manufacturerData = null;
+ solicitationuuids = null, serviceData = null, manufacturerData = null, rssi = null;
if (data) {
address = data.address;
if (data.manufacturerData) {
manufacturerData = new tizen.BluetoothLEManufacturerData(data.manufacturerData);
}
+ if (data.rssi) {
+ rssi = data.rssi;
+ }
}
Object.defineProperties(this, {
manufacturerData : {
value: manufacturerData,
writable: false,
- enumerable: true}
+ enumerable: true},
+ rssi : {value: rssi, writable: false, enumerable: true}
});
};
const std::string kId = "id";
const std::string kData = "data";
const std::string kAction = "action";
+const std::string kRSSI = "rssi";
const std::string kOnConnected = "onconnected";
const std::string kOnDisconnected = "ondisconnected";
g_free(manufacturer_data);
}
+ le_device->insert(
+ std::make_pair(kRSSI,
+ picojson::value(static_cast<double>(info->rssi))));
+
return PlatformResult(ErrorCode::NO_ERROR);
}
#include <algorithm>
#include <memory>
#include <utility>
-
#include "common/filesystem/filesystem_storage.h"
#include "common/logger.h"
namespace {
static const char* kBus = "org.tizen.system.storage";
-static const char* kBlockIface = "org.tizen.system.storage.BlockManager";
-static const char* kBlackManagerIface = "org.tizen.system.storage.BlockManager";
+static const char* kBlockManagerIface = "org.tizen.system.storage.BlockManager";
static const char* kPath = "/Org/Tizen/System/Storage/Block/Manager";
static const char* kDeviceChangedMethod = "DeviceChanged";
static const char* kGetDeviceListMethod = "GetDeviceList";
if (device_changed_callback_ == nullptr) {
LoggerD("Registering dbus signal subscription");
block_signal_subscribe_id_ = g_dbus_connection_signal_subscribe(
- dbus_, nullptr, kBlockIface, kDeviceChangedMethod,
+ dbus_, nullptr, kBlockManagerIface, kDeviceChangedMethod,
nullptr, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, BlockSignalProxy, this,
nullptr);
}
GVariant* variant = g_dbus_connection_call_sync(dbus_,
kBus,
kPath,
- kBlackManagerIface,
+ kBlockManagerIface,
kGetDeviceListMethod,
g_variant_new("(s)", "all"),
NULL,
#include "content/content_manager.h"
#include "common/filesystem/filesystem_provider.h"
+using namespace common;
+
namespace extension {
namespace content {
ContentInstance::ContentInstance() :
noti_handle_(nullptr),
- listener_data_(nullptr) {
+ listener_handle_(nullptr),
+ listener_data_(nullptr),
+ callback_data_(nullptr) {
using std::placeholders::_1;
using std::placeholders::_2;
REGISTER_SYNC("ContentManager_scanFile", ContentManagerScanfile);
REGISTER_SYNC("ContentManager_scanDirectory", ContentManagerScanDirectory);
REGISTER_SYNC("ContentManager_cancelScanDirectory", ContentManagerCancelScanDirectory);
+ REGISTER_SYNC("ContentManager_addChangeListener", ContentManagerAddChangeListener);
+ REGISTER_SYNC("ContentManager_removeChangeListener", ContentManagerRemoveChangeListener);
REGISTER_SYNC("ContentManager_unsetChangeListener", ContentManagerUnsetchangelistener);
REGISTER_SYNC("ContentManager_setChangeListener", ContentManagerSetchangelistener);
REGISTER_SYNC("ContentManager_getDirectories", ContentManagerGetdirectories);
ContentInstance::~ContentInstance() {
LoggerD("entered");
+
if (noti_handle_) {
media_content_remove_db_updated_cb(noti_handle_);
noti_handle_ = nullptr;
}
+
+ if (listener_handle_) {
+ media_content_remove_db_updated_cb(listener_handle_);
+ listener_handle_ = nullptr;
+ }
+
if (listener_data_) {
delete listener_data_;
listener_data_ = nullptr;
}
+
+ if (callback_data_) {
+ delete callback_data_;
+ callback_data_ = nullptr;
+ }
+
ContentManager::getInstance()->setContentInstance(nullptr);
}
common::Instance::PostMessage(cbData->instance, picojson::value(out).serialize().c_str());
}
-
-static void changedContentCallback(media_content_error_e error,
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
+static void changedContentV1Callback(media_content_error_e error,
int pid,
media_content_db_update_item_type_e update_item,
media_content_db_update_type_e update_type,
}
}
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
static void changedContentV2Callback(media_content_error_e error,
int pid,
media_content_db_update_item_type_e update_item,
}
}
+static PlatformResult prepareDirectoryChangeResponse(media_content_db_update_type_e update_type,
+ char* uuid,
+ picojson::object& obj) {
+ LoggerD("Media item is a directory");
+
+ if (MEDIA_CONTENT_DELETE == update_type) {
+ ReportSuccess(picojson::value(std::string(uuid)), obj);
+ obj["state"] = picojson::value("oncontentdirremoved");
+ return PlatformResult(ErrorCode::NO_ERROR);
+ }
+
+ media_folder_h folder = nullptr;
+ int ret = media_folder_get_folder_from_db(uuid, &folder);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == folder) {
+ LoggerE("Failed to get media item (media_folder_get_folder_from_db): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ picojson::object o;
+ ContentDirToJson(folder, o);
+
+ ret = media_folder_destroy(folder);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
+ LoggerE("Failed to destroy media folder (media_folder_destroy): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ ReportSuccess(picojson::value(o), obj);
+
+ if (MEDIA_CONTENT_INSERT == update_type) {
+ obj["state"] = picojson::value("oncontentdiradded");
+ } else if (MEDIA_CONTENT_UPDATE == update_type) {
+ obj["state"] = picojson::value("oncontentdirupdated");
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult prepareFileChangeResponse(media_content_db_update_type_e update_type,
+ char* uuid,
+ picojson::object& obj) {
+ LoggerD("Media item is a file");
+
+ if (MEDIA_CONTENT_DELETE == update_type) {
+ ReportSuccess(picojson::value(std::string(uuid)), obj);
+ obj["state"] = picojson::value("oncontentremoved");
+ return PlatformResult(ErrorCode::NO_ERROR);
+ }
+
+ media_info_h media = nullptr;
+ int ret = media_info_get_media_from_db(uuid, &media);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media) {
+ LoggerE("Failed to get media item (media_info_get_media_from_db): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ picojson::object o;
+ ContentToJson(media, o);
+
+ ret = media_info_destroy(media);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
+ LoggerE("Failed to destroy media info (media_info_destroy): %d", ret);
+ return PlatformResult(ErrorCode::ABORT_ERR);
+ }
+
+ ReportSuccess(picojson::value(o), obj);
+
+ if (MEDIA_CONTENT_INSERT == update_type) {
+ obj["state"] = picojson::value("oncontentadded");
+ } else if (MEDIA_CONTENT_UPDATE == update_type) {
+ obj["state"] = picojson::value("oncontentupdated");
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void contentChangeCallback(media_content_error_e error,
+ int pid,
+ media_content_db_update_item_type_e update_item,
+ media_content_db_update_type_e update_type,
+ media_content_type_e media_type,
+ char* uuid,
+ char* path,
+ char* mime_type,
+ void* user_data) {
+ LoggerD("Entered directory and file change callback");
+
+ if (MEDIA_CONTENT_ERROR_NONE != error) {
+ LoggerE("Failed to perform contentChangeCallback: %d", error);
+ return;
+ }
+
+ if (!uuid) {
+ LoggerE("Provided uuid is NULL, ignoring");
+ return;
+ }
+
+ if (nullptr == user_data) {
+ LoggerE("Provided user data is NULL, ignoring");
+ return;
+ }
+
+ if (MEDIA_ITEM_DIRECTORY != update_item && MEDIA_ITEM_FILE != update_item) {
+ LoggerD("Media item is not a directory nor a file, skipping");
+ return;
+ }
+
+ ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+
+ picojson::value result = picojson::value(picojson::object());
+ picojson::object& obj = result.get<picojson::object>();
+
+ PlatformResult ret(ErrorCode::NO_ERROR);
+ if (MEDIA_ITEM_DIRECTORY == update_item) {
+ ret = prepareDirectoryChangeResponse(update_type, uuid, obj);
+ } else if (MEDIA_ITEM_FILE == update_item) {
+ ret = prepareFileChangeResponse(update_type, uuid, obj);
+ }
+
+ if (ret.IsSuccess()) {
+ obj["listenerId"] = picojson::value("ContentManagerChangeCallback");
+ Instance::PostMessage(cbData->instance, result.serialize().c_str());
+ } else {
+ LoggerD("Failed to prepare content change callback, ignoring");
+ }
+}
+
#define CHECK_EXIST(args, name, out) \
if (!args.contains(name)) {\
LogAndReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, (name" is required argument")), &out);\
}
}
+void ContentInstance::ContentManagerAddChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Entered");
+
+ callback_data_ = new ReplyCallbackData();
+ callback_data_->instance = this;
+ callback_data_->args = args;
+
+ if (ContentManager::getInstance()->isConnected()) {
+ callback_data_->cbType = ContentManagerAddChangeListenerCallback;
+ } else {
+ callback_data_->cbType = ContentManagerErrorCallback;
+ }
+
+ PlatformResult result =
+ ContentManager::getInstance()->addChangeListener(&listener_handle_,
+ contentChangeCallback,
+ static_cast<void*>(callback_data_));
+
+ if (result.IsError()) {
+ delete callback_data_;
+ callback_data_ = nullptr;
+ LogAndReportError(result, &out);
+ }
+}
+
+void ContentInstance::ContentManagerRemoveChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Entered");
+
+ PlatformResult result = ContentManager::getInstance()->removeChangeListener(listener_handle_);
+
+ if (result.IsSuccess()) {
+ listener_handle_ = nullptr;
+ delete callback_data_;
+ callback_data_ = nullptr;
+ } else {
+ LogAndReportError(result, &out);
+ }
+}
void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
picojson::object& out) {
LoggerD("entered");
+ LoggerW("DEPRECATION WARNING: setChangeListener() is deprecated and will be removed from next release. "
+ "Use addChangeListener() instead.");
//CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
listener_data_->cbType = ContentManagerErrorCallback;
}
- if (ContentManager::getInstance()->setChangeListener(changedContentCallback,
+ if (ContentManager::getInstance()->setChangeListener(changedContentV1Callback,
static_cast<void*>(listener_data_)).IsError()) {
LogAndReportError(
common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
}
- if (ContentManager::getInstance()->setV2ChangeListener(¬i_handle_,
- changedContentV2Callback,
- static_cast<void*>(listener_data_)).IsError()) {
- LogAndReportError(
- common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+
+ if (nullptr == noti_handle_) { // To remain consistency with the previous implementation
+ if (ContentManager::getInstance()->addChangeListener(¬i_handle_,
+ changedContentV2Callback,
+ static_cast<void*>(listener_data_)).IsError()) {
+ LogAndReportError(
+ common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+ }
}
}
void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out) {
LoggerD("entered");
+ LoggerW("DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed from next release. "
+ "Use removeChangeListener() instead.");
//CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
if (ContentManager::getInstance()->unSetChangeListener().IsError()) {
LoggerD("unsuccesfull deregistering of callback");
}
- if (ContentManager::getInstance()->unSetV2ChangeListener(¬i_handle_).IsError()) {
+ if (ContentManager::getInstance()->removeChangeListener(noti_handle_).IsError()) {
LoggerD("unsuccesfull deregistering of callback");
+ } else {
+ noti_handle_ = nullptr; // To remain consistency with the previous implementation
}
}
#ifndef CONTENT_CONTENT_INSTANCE_H_
#define CONTENT_CONTENT_INSTANCE_H_
+#include <map>
+
#include <media_content_internal.h>
#include "common/extension.h"
enum ContentCallbacks {
ContentManagerFindCallback,
ContentManagerScanfileCallback,
+ ContentManagerAddChangeListenerCallback,
+ ContentManagerRemoveChangeListenerCallback,
ContentManagerUnsetchangelistenerCallback,
ContentManagerSetchangelistenerCallback,
ContentManagerGetdirectoriesCallback,
void ContentManagerScanfile(const picojson::value& args, picojson::object& out);
void ContentManagerScanDirectory(const picojson::value& args, picojson::object& out);
void ContentManagerCancelScanDirectory(const picojson::value& args, picojson::object& out);
+ void ContentManagerAddChangeListener(const picojson::value& args, picojson::object& out);
+ void ContentManagerRemoveChangeListener(const picojson::value& args, picojson::object& out);
void ContentManagerSetchangelistener(const picojson::value& args, picojson::object& out);
void ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out);
void ContentManagerGetplaylists(const picojson::value& args, picojson::object& out);
void PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out);
void PlaylistGetNumberOfTracks(const picojson::value& args, picojson::object& out);
- media_content_noti_h noti_handle_;
- ReplyCallbackData* listener_data_;
+ media_content_noti_h noti_handle_; // Deprecated handle
+ media_content_noti_h listener_handle_;
+
+ ReplyCallbackData* listener_data_; // Deprecated callback data
+ ReplyCallbackData* callback_data_;
};
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
+PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
+ media_content_db_update_cb callback,
void *user_data) {
LoggerD("Enter");
- int ret = media_content_set_db_updated_cb(callback, user_data);
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
+ int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
+
+ if (MEDIA_CONTENT_ERROR_NONE != ret) {
return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
- ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
+ ErrorCode::ABORT_ERR,
+ "Failed to add the listener.",
+ ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
}
+
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::unSetChangeListener() {
+PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
LoggerD("Enter");
- int ret = media_content_unset_db_updated_cb();
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
- return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
- ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
+ int ret = media_content_remove_db_updated_cb(noti_handle);
+
+ switch (ret) {
+ case MEDIA_CONTENT_ERROR_NONE:
+ return PlatformResult(ErrorCode::NO_ERROR);
+ case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
+ // Trying to remove non-existent listener, ignoring
+ LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
+ return PlatformResult(ErrorCode::NO_ERROR);
+ default:
+ return LogAndCreateResult(
+ ErrorCode::ABORT_ERR,
+ "Failed to remove the listener.",
+ ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
}
- return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::setV2ChangeListener(media_content_noti_h* noti_handle,
- media_content_db_update_cb callback,
+PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
void *user_data) {
LoggerD("Enter");
- if (nullptr == *noti_handle) {
- int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
- if(ret != MEDIA_CONTENT_ERROR_NONE) {
- return LogAndCreateResult(
- ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
- ("Failed: registering the listener of cb_v2 is failed: %d (%s)",
- ret, get_error_message(ret)));
- }
+
+ int ret = media_content_set_db_updated_cb(callback, user_data);
+ if(ret != MEDIA_CONTENT_ERROR_NONE) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
+ ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
}
return PlatformResult(ErrorCode::NO_ERROR);
}
-PlatformResult ContentManager::unSetV2ChangeListener(media_content_noti_h* noti_handle) {
+PlatformResult ContentManager::unSetChangeListener() {
LoggerD("Enter");
- int ret = media_content_remove_db_updated_cb(*noti_handle);
+ int ret = media_content_unset_db_updated_cb();
if(ret != MEDIA_CONTENT_ERROR_NONE) {
return LogAndCreateResult(
ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
- ("Failed: unregistering the listener of cb_v2 is failed %d (%s)",
- ret, get_error_message(ret)));
+ ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
}
- *noti_handle = nullptr;
-
return PlatformResult(ErrorCode::NO_ERROR);
}
-
void ContentManager::createPlaylist(std::string name,
const std::shared_ptr<ReplyCallbackData>& user_data) {
LoggerD("Enter");
int scanFile(std::string& uri);
common::PlatformResult scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData);
common::PlatformResult cancelScanDirectory(const std::string& content_dir_uri);
+ common::PlatformResult addChangeListener(media_content_noti_h* noti_handle,
+ media_content_db_update_cb callback,
+ void *user_data);
+ common::PlatformResult removeChangeListener(media_content_noti_h noti_handle);
common::PlatformResult setChangeListener(media_content_db_update_cb callback,
void *user_data);
common::PlatformResult unSetChangeListener();
- common::PlatformResult setV2ChangeListener(media_content_noti_h* noti_handler,
- media_content_db_update_cb callback,
- void *user_data);
- common::PlatformResult unSetV2ChangeListener(media_content_noti_h* noti_handler);
//Lyrics
int getLyrics(const picojson::value& args,picojson::object& result);
* limitations under the License.
*/
+var T_ = xwalk.utils.type;
+var CONTENT_MANAGER_LISTENER_ID = 'ContentManagerChangeCallback';
+
+
function _ContentManagerChangeCallback(result) {
if (result.state === 'oncontentadded' || result.state === 'oncontentupdated') {
var content = native_.getResultObject(result);
}
}
+
+var ContentListenersManager = (function() {
+
+ function changeContent(event) {
+ if (T_.isEmptyObject(this.listeners)) {
+ return;
+ }
+
+ var result = null;
+
+ if (event.state === 'oncontentadded' || event.state === 'oncontentupdated') {
+ result = createContentObject_(native_.getResultObject(event));
+ } else if (event.state === 'oncontentdiradded' || event.state === 'oncontentdirupdated') {
+ result = createContentDirObject_(native_.getResultObject(event));
+ } else if (event.state === 'oncontentremoved' || event.state === 'oncontentdirremoved') {
+ result = native_.getResultObject(event);
+ }
+
+ if (!result) {
+ return;
+ }
+
+ var callback;
+ for (var listenerId in this.listeners) {
+ if (this.listeners.hasOwnProperty(listenerId)) {
+ callback = this.listeners[listenerId];
+ if (T_.isFunction(callback[event.state])) {
+ callback[event.state](result);
+ }
+ }
+ }
+ }
+
+ function _ContentListenersManager() {
+ this.listeners = {};
+ this.lastListenerId = 0;
+ this.changeContent = changeContent.bind(this);
+ }
+
+ _ContentListenersManager.prototype.addChangeListener = function(changeCallback) {
+ if (T_.isEmptyObject(this.listeners)) {
+ var result = native_.callSync('ContentManager_addChangeListener');
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+
+ native_.addListener(CONTENT_MANAGER_LISTENER_ID, this.changeContent);
+ }
+
+ this.listeners[++this.lastListenerId] = changeCallback;
+ return this.lastListenerId;
+ };
+
+ _ContentListenersManager.prototype.removeChangeListener = function(listenerId) {
+ delete this.listeners[listenerId];
+
+ if (T_.isEmptyObject(this.listeners)) {
+ var result = native_.callSync('ContentManager_removeChangeListener');
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+
+ native_.removeListener(CONTENT_MANAGER_LISTENER_ID);
+ }
+ };
+
+ return _ContentListenersManager;
+})();
+
+var listenersManager = new ContentListenersManager();
+
+
function ContentManager() {
}
}
};
+ContentManager.prototype.addChangeListener = function() {
+ var args = validator_.validateArgs(arguments, [{
+ name: 'changeCallback',
+ type: types_.LISTENER,
+ values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
+ }]);
+
+ return listenersManager.addChangeListener(args.changeCallback);
+};
+
+ContentManager.prototype.removeChangeListener = function() {
+ var args = validator_.validateArgs(arguments, [{
+ name: 'listenerId',
+ type: types_.LONG
+ }]);
+
+ listenersManager.removeChangeListener(args.listenerId);
+};
+
ContentManager.prototype.setChangeListener = function(changeCallback) {
+ console.warn('DEPRECATION WARNING: setChangeListener() is deprecated and will be removed '
+ + 'from next release. Use addChangeListener() instead.');
+
var args = validator_.validateArgs(arguments, [{
name: 'changeCallback',
type: types_.LISTENER,
values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
}]);
- var listenerId = 'ContentManagerChangeCallback';
+ var listenerId = 'ContentManagerChangeCallback_';
var data = {
listenerId: listenerId
oncontentdirremoved: args.changeCallback.oncontentdirremoved
};
- native_.addListener('ContentManagerChangeCallback',
- _ContentManagerChangeCallback.bind(callbacks));
-
var result = native_.callSync('ContentManager_setChangeListener', data);
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
+
+ native_.addListener('ContentManagerChangeCallback_',
+ _ContentManagerChangeCallback.bind(callbacks));
};
ContentManager.prototype.unsetChangeListener = function() {
+ console.warn('DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed '
+ + 'from next release. Use removeChangeListener() instead.');
+
var data = {};
var result = native_.callSync('ContentManager_unsetChangeListener', data);
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
+
+ native_.removeListener('ContentManagerChangeCallback_');
};
ContentManager.prototype.getPlaylists = function(successCallback, errorCallback) {
--- /dev/null
+{
+ 'includes':[
+ '../common/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'tizen_convergence',
+ 'type': 'loadable_module',
+ 'dependencies': [
+ '../common/common.gyp:tizen_common',
+ ],
+ 'sources': [
+ 'convergence_api.js',
+ 'convergence_extension.cc',
+ 'convergence_extension.h',
+ 'convergence_instance.cc',
+ 'convergence_instance.h',
+ 'convergence_utils.cc',
+ 'convergence_utils.h',
+ 'convergence_manager.cc',
+ 'convergence_manager.h',
+ 'convergence_device.cc',
+ 'convergence_device.h',
+ 'convergence_service.cc',
+ 'convergence_service.h',
+ 'convergence_remote_app_control_service.cc',
+ 'convergence_remote_app_control_service.h',
+ 'convergence_app_communication_service.cc',
+ 'convergence_app_communication_service.h',
+ 'convergence_channel.cc',
+ 'convergence_channel.h',
+ 'convergence_payload.cc',
+ 'convergence_payload.h',
+ 'convergence_client_info.cc',
+ 'convergence_client_info.h',
+ ],
+ 'conditions': [
+ ['tizen == 1', {
+ 'variables': {
+ 'packages': [
+ 'd2d-conv-manager',
+ ]
+ },
+ }],
+ ],
+ },
+ ],
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var utils_ = xwalk.utils;
+var native_ = new utils_.NativeManager(extension);
+var T_ = utils_.type;
+
+// Flag showing if the discovery procedure has started
+var discoveryStarted = false;
+
+// Currently available devices
+var convergenceDevices = [];
+
+// Issued service objects
+// We should stor it for proper calling user callbacks
+var nextServiceId = 0; // Next service id (internally used on JS layer)
+var convergenceServices = {}; // Issued services
+
+var ConnectionState = {
+ CONNECTED: 'CONNECTED',
+ NOT_CONNECTED: 'NOT_CONNECTED',
+ CONNECTING: 'CONNECTING'
+};
+
+var DeviceProfile = {
+ MOBILE: 'MOBILE',
+ WEARABLE: 'WEARABLE',
+ TV: 'TV'
+};
+
+
+var PayloadType = {
+ STRING: 'STRING',
+ RAW_BYTES: 'RAW_BYTES'
+};
+
+function SetReadOnlyProperty(obj, n, v) {
+ if (arguments.length > 2)
+ Object.defineProperty(
+ obj, n, {
+ value: v,
+ writable: false,
+ enumerable: true,
+ configurable: true
+ });
+ else
+ Object.defineProperty(obj, n, {
+ writable: false,
+ enumerable: true,
+ configurable: true
+ });
+}
+
+
+function getServiceConnectionStateName(connectionStateNumber) {
+ switch(connectionStateNumber) {
+ case 0:
+ return ConnectionState.CONNECTED;
+ case 1:
+ return ConnectionState.NOT_CONNECTED;
+ case 2:
+ return ConnectionState.CONNECTING;
+ default:
+ console.log('ERROR: Unknown connection state');
+ return -1; // TODO throw exception
+ }
+}
+
+function Device(id, name, profile, services) {
+ validator_.isConstructorCall(this, Device);
+ this.id = id;
+ this.name = name;
+ this.profile = profile;
+ this.services = services;
+}
+
+function ConvergenceManager() {
+ // constructor of ConvergenceManager
+}
+
+ConvergenceManager.prototype.startDiscovery = function(successCallback,
+ errorCallback, timeout) {
+ console.log('Entered ConvergenceManager.startDiscovery()');
+ var args = validator_.validateArgs(arguments, [
+ {name: 'successCallback', type: types_.LISTENER, values: ['onfound', 'onfinished' ]},
+ {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+ {name: 'timeout', type: types_.LONG, optional: true, nullable: true}
+ ]);
+
+ // Indicate, that discovery procedure is on
+ discoveryStarted = true;
+
+ // Reset currently available device list
+ convergenceDevices = [];
+
+ native_.addListener('CONVERGENCE_DISCOVERY_LISTENER', function(result) {
+ console.log('Entered discovery listener');
+
+ if (native_.isFailure(result)) {
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ } else {
+ if (result.discovery_status == 'device_found') {
+
+ // Prepare service array
+ if (!result || !result.device || !result.device.services) {
+ console.log('INVALID device info obtained from Native API'); // TODO throw exception
+ return;
+ }
+
+ // Create an instance of the device
+ var d = new Device(result.device.id, result.device.name, result.device.type, []);
+
+ console.log('Service number: ' + result.device.services.length);
+ for (var i = 0; i < result.device.services.length; ++i) {
+ var service_data = result.device.services[i];
+ var s;
+ if (service_data.serviceType == 0) { // App Communication Client
+ s = new AppCommunicationClientService();
+ } else if (service_data.serviceType == 1) { // Remote App Control
+ s = new RemoteAppControlService();
+ } else {
+ // Error: unknown service type
+ // TODO throw exception
+ console.log('UNKNOWN SERVICE TYPE: ' + service_data.serviceType);
+ continue;
+ }
+
+ s.connectionState = getServiceConnectionStateName(
+ result.device.services[i].connectionState);
+ s._deviceId = d.id;
+ d.services.push(s);
+ }
+
+ // Store newly found device internally
+ convergenceDevices.push(d);
+
+ // Invoke user callback retrieving newly found device
+ native_.callIfPossible(successCallback.onfound, d);
+
+ } else if (result.discovery_status == 'discovery_finished') {
+ // Unregister discovery listener, because Convergence Manager is a
+ // singleton object and no one else can receive discovery results
+ native_.removeListener('CONVERGENCE_DISCOVERY_LISTENER');
+
+ // Notify the customer about discovery results
+ native_.callIfPossible(successCallback.onfinished, convergenceDevices.slice());
+ convergenceDevices = [];
+
+ } else {
+ console.log('UNKNOWN discovery state exception'); // TODO throw exception
+ }
+ }
+ });
+
+ // Start the discovery using Native API
+ var result = native_.call('ConvergenceManager_startDiscovery', {
+ timeout: (args.timeout) ? args.timeout : 0
+ }, function(result) {
+ if (native_.isFailure(result)) {
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ }
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+ConvergenceManager.prototype.stopDiscovery = function() {
+ console.log('Entered ConvergenceManager.stopDiscovery()');
+
+ if (!discoveryStarted)
+ throw new WebAPIException('InvalidStateError', 'Discovery has not started yet.');
+
+ discoveryStarted = false;
+
+ var result = native_.callSync('ConvergenceManager_stopDiscovery', null);
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+function Service() {
+ console.log('Entered Service.constructor()');
+
+ //validator_.isConstructorCall(this, Service);
+ this.connectionState = ConnectionState.NOT_CONNECTED;
+}
+
+native_.addListener('REMOTE_APP_CONTROL_SERVICE_LISTENER', function(result) {
+ if (native_.isFailure(result)) {
+ //native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ console.log('Error in REMOTE_APP_CONTROL_SERVICE_LISTENER');
+ } else {
+
+ console.log('');
+ console.log('REMOTE_APP_CONTROL_SERVICE_LISTENER invoked with data');
+ console.log(JSON.stringify(result));
+ console.log('');
+
+ // Invoke corresponding callback
+ var lid = result.curListenerId;
+ if (!lid || !convergenceServices.hasOwnProperty(lid)) {
+ console.log('ERROR: Remote App Ctrl listener is not registered [' + lid + ']');
+ return; // Something is wrong: listener MUST be there
+ }
+ var s = convergenceServices[lid];
+
+ var result_type = result.result_type;
+
+ switch (result_type) {
+ case 'Connected':
+ if (s) { // Service MUST NOT be null here
+ s.connectionState = ConnectionState.CONNECTED;
+ convergenceServices[lid] = s;
+ }
+ native_.callIfPossible(s._connectCallback, s);
+ break;
+ case 'onPublish':
+ native_.callIfPossible(s._remoteAppControlCallback,
+ result.payload);
+ break;
+ default:
+ console.log('Ignoring result type: [' + result_type + ']');
+ break;
+ }
+ }
+});
+
+function RemoteAppControlService() {
+ console.log('Entered RemoteAppControlService.constructor()');
+
+ validator_.isConstructorCall(this, RemoteAppControlService);
+
+ // The device id is needed for getting the valid service handle on the
+ // native layer
+ // I have to implement this property here instead of base constructor in order
+ // to mask it from accessing
+ Object.defineProperties(this, {
+ _serviceId : {
+ value: ++nextServiceId,
+ writable: false,
+ enumerable: false
+ },
+ // The id of device of the service or 'localhost' for local service
+ _deviceId : {
+ value: 'localhost',
+ writable: true,
+ enumerable: false
+ },
+ // Remote App Control Service user-defined callbacks
+ _connectCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _remoteAppControlCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ }
+ });
+
+ // Registering the service in the table of issued services
+ convergenceServices[this._serviceId] = this;
+}
+
+RemoteAppControlService.prototype = new Service();
+
+RemoteAppControlService.prototype.connect = function(successCallback, errorCallback) {
+ console.log('Entered RemoteAppControlService.connect()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ if (this.serviceState == ConnectionState.CONNECTED)
+ throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+ var lid = this._serviceId;
+ this._connectCallback = successCallback;
+ convergenceServices[lid] = this;
+
+ var result = native_.call('RemoteAppControlService_connect', {
+ deviceId: this._deviceId,
+ curListenerId: lid
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+RemoteAppControlService.prototype.disconnect = function(successCallback, errorCallback) {
+ console.log('Entered RemoteAppControlService.disconnect()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ if (this.serviceState != ConnectionState.CONNECTED) {
+ throw new WebAPIException('InvalidStateError', 'Service is not connected yet.');
+ }
+
+ var result = native_.callSync('RemoteAppControlService_disconnect', {
+ deviceId: this._deviceId
+ });
+
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+ else
+ connectionState = ConnectionState.DISCONNECTED;
+
+ native_.callIfPossible(successCallback, this);
+};
+
+RemoteAppControlService.prototype.launch = function(appId, successCallback, errorCallback) {
+ console.log('Entered RemoteAppControlService.launch()');
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'appId',
+ //type: types_.PLATFORM_OBJECT,
+ type: types_.STRING,
+ values: tizen.ApplicationId,
+ optional: false,
+ nullable:false
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: RemoteAppControlCallback,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ if (this.serviceState == ConnectionState.CONNECTED)
+ throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+ var lid = this._serviceId;
+ // TODO In fact it must be a list of callbacks
+ // But untill D2D FW suppurts transaction management, it is meaningless to
+ // have more than one callback, because all payload is delivered to
+ // a single point without identification of initial request
+ this._remoteAppControlCallback = successCallback;
+ convergenceServices[lid] = this;
+
+ var needReply = !(successCallback == null);
+
+ var result = native_.call('RemoteAppControlService_launch', {
+ appId: args.appId,
+ reply: needReply,
+ deviceId: this._deviceId,
+ curListenerId: lid
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+RemoteAppControlService.prototype.launchAppControl = function(
+ appControl, appId, successCallback, errorCallback) {
+ console.log('Entered RemoteAppControlService.launchAppControl()');
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'appControl',
+ type: types_.PLATFORM_OBJECT,
+ values: tizen.ApplicationControl,
+ optional: false,
+ nullable:false
+ },
+ {
+ name: 'appId',
+ type: types_.PLATFORM_OBJECT,
+ values: tizen.ApplicationId,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: RemoteAppControlCallback,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ // TODO Implement pls
+
+ return; // TODO remove when native layer is implemented
+};
+
+function AppCommunicationService() {
+ console.log('Entered AppCommunicationService.constructor()');
+
+ // The device id is needed for getting the valid service handle on the
+ // native layer
+ // I have to implement this property here instead of base constructor in order
+ // to mask it from accessing
+ Object.defineProperties(this, {
+ _serviceId : {
+ value: ++nextServiceId,
+ writable: false,
+ enumerable: false
+ },
+ // The id of device of the service or 'localhost' for local service
+ _deviceId : {
+ value: 'localhost',
+ writable: true,
+ enumerable: false
+ },
+ // App Communication Service basic callbacks
+ _connectCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _startCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _sendCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _stopCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _listenerCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ },
+ _getClientListCallback : {
+ value: null,
+ writable: true,
+ enumerable: false
+ }
+ });
+
+ // TODO add callbacks in runtime instead of constructor
+
+ // Registering the service in the table of issued services
+ convergenceServices[this._serviceId] = this;
+}
+
+AppCommunicationService.prototype = new Service();
+
+native_.addListener('APP_COMMUNICATION_SERVICE_LISTENER', function(result) {
+
+ console.log('On App Communication Service Success Callback');
+
+ if (native_.isFailure(result)) {
+ console.log('ERROR in APP_COMMUNICATION_SERVICE_LISTENER');
+ //native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ } else {
+
+ console.log('');
+ console.log('APP_COMMUNICATION_SERVICE_LISTENER invoked with data');
+ console.log(JSON.stringify(result));
+ console.log('');
+
+ // Invoke corresponding callback
+ var lid = result.curListenerId;
+ if (!lid || !convergenceServices.hasOwnProperty(lid)) {
+ console.log('ERROR: App Comm listener is not registered [' + lid + ']');
+ return; // Something is wrong: listener MUST be there
+ }
+ var s = convergenceServices[lid];
+
+ var result_type = result.result_type;
+
+ switch (result_type) {
+ case 'Connected':
+ if (s) { // Service MUST NOT be null here
+ s.connectionState = ConnectionState.CONNECTED;
+ convergenceServices[lid] = s;
+ }
+ native_.callIfPossible(s._connectCallback, s);
+ break;
+ case 'onStart':
+ native_.callIfPossible(s._startCallback,
+ new Channel(result.channel.uri, result.channel.id), null);
+ break;
+ case 'onPublish':
+ native_.callIfPossible(s._sendCallback,
+ new Channel(result.channel.uri, result.channel.id), null);
+ break;
+ case 'onStop':
+ native_.callIfPossible(s._stopCallback,
+ new Channel(result.channel.uri, result.channel.id), null);
+ break;
+ case 'onMessage': {
+ var payload = [];
+ for(var i = 0; i < result.payload.length; i++) {
+ var curPl = result.payload[i];
+ switch(curPl.type) {
+ case PayloadType.STRING:
+ payload.push(new PayloadString(curPl.key, curPl.value));
+ break;
+ case PayloadType.RAW_BYTES:
+ payload.push(new PayloadRawBytes(curPl.key, curPl.value));
+ break;
+ default:
+ console.log('ERROR: Unknown payload type');
+ break;
+ }
+ }
+
+ native_.callIfPossible(s._listenerCallback,
+ new Channel(result.channel.uri, result.channel.id),
+ payload, result.senderId);
+ }
+ break;
+ default:
+ console.log('Ignoring result type: [' + result_type + ']');
+ break;
+ }
+
+ /*
+ // TODO uncomment when implemented (or remove thid data from the protocol)
+ *var clientInfo = new ClientInfo(
+ result.clientInfo.isHost,
+ result.clientInfo.lientId,
+ result.clientInfo.connectionTime);*
+ var clientInfo = null;
+ */
+ }
+});
+
+AppCommunicationService.prototype.start = function(channel, successCallback, errorCallback) {
+ console.log('Entered AppCommunicationService.start()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'channel',
+ type: types_.PLATFORM_OBJECT,
+ values: tizen.Channel,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ // TODO check if the service is connected and started
+ // Raise the exception instead
+
+ var lid = this._serviceId;
+ this._startCallback = successCallback;
+ convergenceServices[lid] = this;
+
+ var result = native_.call('AppCommunicationService_start', {
+ deviceId: this._deviceId,
+ curListenerId: lid,
+ channel_data: channel
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.stop = function(channel, successCallback, errorCallback) {
+ console.log('Entered AppCommunicationService.stop()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'channel',
+ type: types_.PLATFORM_OBJECT,
+ values: tizen.Channel,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ // TODO check if the service is connected and started
+ // Raise the exception instead
+
+ var lid = -1;
+ if (successCallback) {
+ lid = this._serviceId;
+ this._stopCallback = successCallback;
+ convergenceServices[lid] = this;
+ }
+
+ var result = native_.call('AppCommunicationService_stop', {
+ deviceId: this._deviceId,
+ curListenerId: lid,
+ channel_data: channel
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.send = function(channel, payload, successCallback, errorCallback) {
+ console.log('Entered AppCommunicationService.send()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'channel',
+ type: types_.PLATFORM_OBJECT,
+ values: tizen.Channel,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'payload',
+ type: types_.PLATFORM_OBJECT,
+ values: [tizen.PayloadString, tizen.PayloadRawBytes],
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ // TODO check if the service is connected and started
+ // Raise the exception instead
+
+ var lid = this._serviceId;
+ this._sendCallback = successCallback;
+ convergenceServices[lid] = this;
+
+ var result = native_.call('AppCommunicationService_send', {
+ deviceId: this._deviceId,
+ curListenerId: lid,
+ channel_data: channel,
+ payload: payload
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.addListener = function(listenerCallback) {
+ console.log('Entered AppCommunicationService.addListener()');
+ var args = validator_.validateArgs(arguments, [
+ {name: 'listenerCallback', type: types_.FUNCTION}
+ ]);
+
+ var lid = this._serviceId;
+ // TODO in fact, it should be even the list of callbacks instead of
+ // the single callback
+ this._listenerCallback = listenerCallback;
+ convergenceServices[lid] = this;
+
+ console.log('');
+ console.log('AppCommunicationServiceCommandListeners ADDED [' + lid + ']');
+ console.log('');
+
+ var result = native_.callSync('AppCommunicationService_addListener', {
+ deviceId: this._deviceId,
+ curListenerId: lid
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+
+ return args.curListenerId; // TODO return proper index of listener
+};
+
+AppCommunicationService.prototype.removeListener = function(id) {
+ console.log('Entered AppCommunicationService.removeListener()');
+ var args = validator_.validateArgs(arguments, [
+ {name: 'id', type: types_.LONG, optional: false}
+ ]);
+
+ var result = native_.callSync('AppCommunicationService_removeListener', {
+ deviceId: this._deviceId
+ //curListenerId: id // not needed in below layers
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+
+ var lid = this._serviceId;
+ if (this._listenerCallback) {// TODO extend this to manage the list of callbacks
+ //delete this._listenerCallback;
+ this._listenerCallback = null;
+ }
+ convergenceServices[lid] = this;
+};
+
+function AppCommunicationServerService() {
+ console.log('Entered AppCommunicationServerService.constructor()');
+
+ validator_.isConstructorCall(this, AppCommunicationServerService);
+
+ this.connectionState = ConnectionState.NOT_CONNECTED;
+
+ native_.callSync('AppCommunicationServerService_constructLocal', {
+ deviceId: this._deviceId
+ });
+}
+
+AppCommunicationServerService.prototype = new AppCommunicationService();
+
+function AppCommunicationClientService() {
+ console.log('Entered AppCommunicationClientService.constructor()');
+
+ validator_.isConstructorCall(this, AppCommunicationClientService);
+
+ this.connectionState = ConnectionState.NOT_CONNECTED;
+}
+
+AppCommunicationClientService.prototype = new AppCommunicationService();
+
+AppCommunicationClientService.prototype.connect = function(successCallback, errorCallback) {
+ console.log('Entered AppCommunicationClientService.connect()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: false,
+ nullable: false
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ if (this.serviceState == ConnectionState.CONNECTED)
+ throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+ var lid = this._serviceId;
+ this._connectCallback = successCallback;
+ convergenceServices[lid] = this;
+
+ var result = native_.call('AppCommunicationClientService_connect', {
+ deviceId: this._deviceId,
+ curListenerId: lid
+ }, function(result) {
+ if (native_.isFailure(result))
+ native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+ });
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+};
+
+AppCommunicationClientService.prototype.disconnect = function(successCallback, errorCallback) {
+ console.log('Entered AppCommunicationClientService.disconnect()');
+
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION,
+ //values: ConnectSuccessCallback,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ //values: ErrorCallback,
+ optional: true,
+ nullable: true
+ }
+ ]);
+ if (this.serviceState != ConnectionState.CONNECTED)
+ throw new WebAPIException('InvalidStateError', 'Service is not connected yet.');
+
+ var result = native_.callSync('AppCommunicationClientService_disconnect', {
+ deviceId: this._deviceId
+ });
+
+ if (native_.isFailure(result))
+ throw native_.getErrorObject(result);
+ else
+ connectionState = ConnectionState.DISCONNECTED;
+
+ native_.callIfPossible(successCallback, this);
+};
+
+function Channel(uri, id) {
+ validator_.isConstructorCall(this, Channel);
+ this.uri = uri;
+ this.id = id;
+}
+
+function PayloadString(key, value) {
+ validator_.isConstructorCall(this, PayloadString);
+ this.key = key;
+ this.value = value;
+ SetReadOnlyProperty(this, 'type', PayloadType.STRING); // read only property
+}
+
+function PayloadRawBytes(key, value) {
+ validator_.isConstructorCall(this, PayloadRawBytes);
+ this.key = key;
+ this.value = value;
+ SetReadOnlyProperty(this, 'type', PayloadType.RAW_BYTES); // read only property
+}
+
+function ClientInfo(isHost, clientId, connectionTime) {
+ validator_.isConstructorCall(this, ClientInfo);
+ this.isHost = isHost;
+ this.clientId = clientId;
+ this.connectionTime = connectionTime;
+}
+
+exports = new ConvergenceManager();
+tizen.RemoteAppControlService = RemoteAppControlService;
+tizen.AppCommunicationServerService = AppCommunicationServerService;
+tizen.AppCommunicationClientService = AppCommunicationClientService;
+tizen.Channel = Channel;
+tizen.PayloadString = PayloadString;
+tizen.PayloadRawBytes = PayloadRawBytes;
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_app_communication_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+#include <stdlib.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_channel.h"
+#include "convergence/convergence_payload.h"
+#include "convergence/convergence_client_info.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+namespace {
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; // ---
+static const std::string kServiceConnectionStatusConnected = "service_connected";
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected";
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+ConvergenceAppCommunicationService::ConvergenceAppCommunicationService()
+ : ConvergenceService() {
+ ScopeLogger();
+}
+
+ConvergenceAppCommunicationService::ConvergenceAppCommunicationService(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceService(device, CONV_SERVICE_APP_TO_APP_COMMUNICATION, convergence_plugin) {
+ ScopeLogger();
+}
+
+ConvergenceAppCommunicationService::~ConvergenceAppCommunicationService() {
+ ScopeLogger();
+
+ // Release all memory, used by callback paramerers
+ for (size_t i = 0; i < callback_param_gc_.size(); i++) {
+ delete callback_param_gc_[i];
+ }
+ callback_param_gc_.clear();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Start(
+ ConvergenceChannel *channel,
+ const int cur_listener_id) {
+ ScopeLogger();
+
+ LoggerI("Starting service [0x%x] with handle [0x%x]", this, service_handle_);
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+LoggerI("1");
+
+ UpdateListener(cur_listener_id);
+
+LoggerI("2");
+
+
+ { // DBG
+ conv_channel_h ch = channel->GetHandle();
+ char *id = NULL;
+ conv_channel_get_string(ch, "channel_id", &id);
+ char *uri = NULL;
+ conv_channel_get_string(ch, "uri", &uri);
+ LoggerI("===== CHANNEL ID [%s] URI [%s]", id, uri);
+ }
+
+ const int error = conv_service_start(service_handle,
+ channel->GetHandle(), nullptr);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_start");
+ }
+
+LoggerI("3");
+ delete channel;
+LoggerI("4");
+ return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Stop(
+ ConvergenceChannel *channel,
+ const int cur_listener_id) {
+ ScopeLogger();
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ UpdateListener(cur_listener_id);
+
+ const int error = conv_service_stop(service_handle,
+ channel->GetHandle(), nullptr);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_stop");
+ }
+
+ delete channel;
+ return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Send(
+ ConvergenceChannel *channel,
+ ConvergencePayloadArray *payload,
+ const int cur_listener_id) {
+ ScopeLogger();
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ UpdateListener(cur_listener_id);
+
+ { // DBG
+ LoggerI("...PUBLISHING for service handle [0x0%x]", service_handle);
+
+ conv_service_e t = CONV_SERVICE_NONE;
+ int e = conv_service_get_type(service_handle, &t);
+ if (CONV_ERROR_NONE != e) {
+ trace_conv_error(e, __LINE__, "get service type");
+ }
+ LoggerI("....type [%d]", t);
+
+ char *sid = nullptr;
+ e = conv_service_get_property_string(service_handle, CONV_SERVICE_ID, &sid);
+ if (CONV_ERROR_NONE != e) {
+ trace_conv_error(e, __LINE__, "get service id");
+ }
+ LoggerI("....id [%s]", sid);
+ free(sid);
+
+ conv_channel_h ch = channel->GetHandle();
+ char *id = NULL;
+ conv_channel_get_string(ch, "channel_id", &id);
+ char *uri = NULL;
+ conv_channel_get_string(ch, "uri", &uri);
+ LoggerI("===== CHANNEL ID [%s] URI [%s]", id, uri);
+ }
+
+ const int error = conv_service_publish(service_handle,
+ channel->GetHandle(), payload->GetHandle());
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_publish");
+ } else {
+ LoggerI("PUBLISHED SUCCESSFULY listener is [%d]", cur_listener_id);
+ }
+
+ delete channel;
+ delete payload;
+ return TizenSuccess();
+}
+
+
+// TODO move to Payload class
+
+
+void ConvergenceAppCommunicationService::ServiceListenerCb(conv_service_h service_handle,
+ conv_channel_h channel_handle,
+ conv_error_e error, conv_payload_h result, void* user_data) {
+ ScopeLogger();
+
+ CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+ if (!callbackParam) {
+ LoggerE("ERROR! NULL user data in Service Listener Callback");
+ return;
+ }
+
+ // TODO Send all payload and channel to the JS layer and parse it there
+
+ // TODO parse the payload and fill the param
+ LoggerI("YAY! Got the Callback (TODO implement it)");
+
+ if (CONV_ERROR_NONE != error) { // Error occured during connection
+ picojson::object param;
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusError);
+ param[kServiceListenerError] = picojson::value(static_cast<double>(error));
+ callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ callbackParam->callback_id_, false, param);
+ return;
+ }
+
+ // Parse the payload
+ const std::string result_type = ConvergencePayloadArray::ExtractPayloadString(result, "result_type"); // TODO extract to constant kResultType = "result_type";
+ LoggerI("Callback type [%s]", result_type.c_str());
+
+ picojson::object param;
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+ param["channel"] = ConvergenceChannel::ToJson(channel_handle);
+ param["result_type"] = picojson::value(result_type);
+
+ if (("onStart" == result_type)
+ || ("onPublish" == result_type)
+ || ("onStop" == result_type)) {
+ // The service doesn't send any callback with thie response
+ } else if ("onMessage" == result_type) {
+ param["senderId"] = picojson::value(
+ ConvergencePayloadArray::ExtractPayloadString(result, "from")); // Define the string as a constant
+ param["payload"] = ConvergencePayloadArray::ToJson(result);
+ } else if ("onConnect" == result_type) {
+ //param["clientInfo"] = ConvergenceClientInfo(result).ToJson();
+ //callbackParam->plugin_->ReplyAsync(kAppCommunicationClientServiceConnectCallback,
+ // callbackParam->callback_id_, true, param);
+ return;
+ } else if ("onClientConnect" == result_type) {
+ // TODO the service doesn't send any callback with thie response
+ return; // TODO
+ } else if ("onDisconnect" == result_type) {
+ return; // TODO
+ } else if ("onClientDisconnect" == result_type) {
+ return; // TODO
+ } else if ("onRead" == result_type) {
+ // TODO
+ } else {
+ // Unsupported payload type, ignoring it
+ LoggerE("ERROR: Unsupported payload type; ignored");
+ return;
+ }
+
+ callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ callbackParam->callback_id_, true, param);
+
+ // TODO Remove callbackParam from GC
+ // TODO delete callbackParam
+}
+
+void ConvergenceAppCommunicationService::UpdateListener(const int cur_listener_id) {
+ ScopeLogger();
+
+ // TODO make sure that callback is not called twice for the same listener
+
+ // TODO: make a garbage collection and release this memory when callback unset
+ // and when whole manager is destructed
+ CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+ callback_param_gc_.push_back(param);
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return;
+ }
+
+ { // dbg
+ LoggerI("...found service handle [%x0x]", service_handle);
+
+ conv_service_e t = CONV_SERVICE_NONE;
+ int e = conv_service_get_type(service_handle, &t);
+ if (CONV_ERROR_NONE != e) {
+ trace_conv_error(e, __LINE__, "get service type");
+ }
+ LoggerI("....type [%d]", t);
+
+ char *sid = nullptr;
+ e = conv_service_get_property_string(service_handle, CONV_SERVICE_ID, &sid);
+ if (CONV_ERROR_NONE != e) {
+ trace_conv_error(e, __LINE__, "get service id");
+ }
+ LoggerI("....id [%s]", sid);
+ free(sid);
+
+ char *sver = nullptr;
+ e = conv_service_get_property_string(service_handle, CONV_SERVICE_VERSION, &sver);
+ if (CONV_ERROR_NONE != e) {
+ trace_conv_error(e, __LINE__, "get service version");
+ }
+ LoggerI("....ver [%s]", sver);
+ free(sver);
+ }
+
+ const int error = conv_service_set_listener_cb(service_handle, ServiceListenerCb, param);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+ } else {
+ LoggerI("APP COMMUNICATION SERVICE LISTENER SET SUCCESSFULY [%d]", cur_listener_id);
+ }
+}
+
+common::TizenResult ConvergenceAppCommunicationService::SetListener(const int cur_listener_id) {
+ ScopeLogger();
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle)
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+
+ UpdateListener(cur_listener_id);
+
+ return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::RemoveListener() {
+ ScopeLogger();
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ const int error = conv_service_unset_listener_cb(service_handle);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+ return LogAndCreateTizenError(NotFoundError,
+ "Unset Listener Failed");
+ }
+
+ return TizenSuccess();
+}
+
+picojson::value ConvergenceAppCommunicationService::PayloadToJson(conv_payload_h payload) {
+ ScopeLogger();
+ picojson::value payload_json;
+
+ // TODO convert payload to array of ApplicationControlData
+
+ return payload_json;
+}
+
+
+
+ConvergenceAppCommunicationServerService::ConvergenceAppCommunicationServerService()
+ : ConvergenceAppCommunicationService() {
+ ScopeLogger();
+}
+
+ConvergenceAppCommunicationServerService::ConvergenceAppCommunicationServerService(
+ conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceAppCommunicationService(device, convergence_plugin) {
+ ScopeLogger();
+
+ // Creating the handle of local service instance
+ int error = conv_service_create(&service_handle_);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_create App Comm Service");
+ }
+
+ error = conv_service_set_type(service_handle_, CONV_SERVICE_APP_TO_APP_COMMUNICATION);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_type App Comm Service");
+ }
+
+ /*
+ * Consider a constructor of App Communication Server Service with parameters:
+ * - Id
+ * - Version
+ */
+
+ error = conv_service_set_property_string(service_handle_, CONV_SERVICE_ID, "test_app"); // TODO set a proper service ID
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_property Id");
+ }
+
+ error = conv_service_set_property_string(service_handle_, CONV_SERVICE_VERSION, "1.0");
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_property Version");
+ }
+}
+
+ConvergenceAppCommunicationServerService::~ConvergenceAppCommunicationServerService() {
+ ScopeLogger();
+}
+
+common::TizenResult ConvergenceAppCommunicationServerService::Start(
+ ConvergenceChannel *channel,
+ const int cur_listener_id) {
+ ScopeLogger();
+
+
+ /* By implementation, the local App Communication Service doesn't send
+ * the callback confirming that the Start is successful.
+ * So we are sending this callback manually
+ */
+ picojson::object param;
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+
+ // The object 'channel' will be deleted in the super::Start() so we should
+ // add its json before
+ param["channel"] = ConvergenceChannel::ToJson(channel->GetHandle()); // Define string as constant
+ param["result_type"] = picojson::value("onStart");
+
+ common::TizenResult result = ConvergenceAppCommunicationService::Start(
+ channel, cur_listener_id);
+
+ // TODO check if result value is OK
+
+ convergence_plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ cur_listener_id, true, param);
+ return result;
+}
+
+common::TizenResult ConvergenceAppCommunicationServerService::Stop(
+ ConvergenceChannel *channel,
+ const int cur_listener_id) {
+ ScopeLogger();
+
+ /* By implementation, the local App Communication Service doesn't send
+ * the callback confirming that the Start is successful.
+ * So we are sending this callback manually
+ */
+ picojson::object param;
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+
+ // The object 'channel' will be deleted in the super::Start() so we should
+ // add its json before
+ param["channel"] = ConvergenceChannel::ToJson(channel->GetHandle());
+ param["result_type"] = picojson::value("onStop");
+
+ common::TizenResult result = ConvergenceAppCommunicationService::Stop(
+ channel, cur_listener_id);
+
+ // TODO check if result value is OK
+
+ convergence_plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ cur_listener_id, true, param);
+ return result;
+}
+
+ConvergenceAppCommunicationClientService::ConvergenceAppCommunicationClientService()
+ : ConvergenceAppCommunicationService() {
+ ScopeLogger();
+}
+
+ConvergenceAppCommunicationClientService::ConvergenceAppCommunicationClientService(
+ conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceAppCommunicationService(device, convergence_plugin) {
+ ScopeLogger();
+}
+
+ConvergenceAppCommunicationClientService::~ConvergenceAppCommunicationClientService() {
+ ScopeLogger();
+}
+
+void ConvergenceAppCommunicationClientService::ServiceConnectedCb(conv_service_h service_handle,
+ conv_error_e error, conv_payload_h result, void* user_data) {
+ ScopeLogger();
+
+ CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+ if (!callbackParam) {
+ LoggerE("ERROR! NULL user data in Service Connect Callback");
+ return;
+ }
+
+ picojson::object param;
+ param[kPayload] = ConvergenceAppCommunicationService::PayloadToJson(result);
+ param["result_type"] = picojson::value("Connected");
+
+ if (CONV_ERROR_NONE == error) {
+ param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusConnected);
+ callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ callbackParam->callback_id_,
+ true,
+ param);
+ } else {
+ // Error occured during connection
+ param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusNotConnected);
+ callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+ callbackParam->callback_id_,
+ false,
+ param);
+ }
+}
+
+common::TizenResult ConvergenceAppCommunicationClientService::Connect(const int cur_listener_id) {
+ ScopeLogger();
+
+ conv_service_h service = FindServiceHandle();
+ if (!service) {
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ // TODO: make a garbage collection and release this memory when service is disconnected
+ // and when whole manager is destructed
+ CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+ callback_param_gc_.push_back(param);
+
+ const int error = conv_service_connect(service, ServiceConnectedCb, param);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_connect");
+ }
+
+ return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationClientService::Disconnect() {
+ ScopeLogger();
+
+ conv_service_h service = FindServiceHandle();
+ if (!service)
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+
+ const int error = conv_service_disconnect(service);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_disconnect");
+ }
+
+ return TizenSuccess();
+}
+
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceChannel;
+class ConvergencePayloadArray;
+
+class ConvergenceAppCommunicationService : public ConvergenceService {
+ public:
+ ConvergenceAppCommunicationService();
+ ConvergenceAppCommunicationService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceAppCommunicationService();
+ ConvergenceAppCommunicationService(const ConvergenceAppCommunicationService&) = delete;
+ ConvergenceAppCommunicationService(ConvergenceAppCommunicationService&&) = delete;
+ ConvergenceAppCommunicationService& operator=(const ConvergenceAppCommunicationService&) = delete;
+ ConvergenceAppCommunicationService& operator=(ConvergenceAppCommunicationService&&) = delete;
+ public:
+ virtual common::TizenResult Start(ConvergenceChannel *channel,
+ const int cur_listener_id);
+ virtual common::TizenResult Stop(ConvergenceChannel *channel,
+ const int cur_listener_id);
+ virtual common::TizenResult Send(ConvergenceChannel *channel,
+ ConvergencePayloadArray *payload,
+ const int cur_listener_id);
+ common::TizenResult SetListener(const int cur_listener_id);
+ common::TizenResult RemoveListener();
+ protected:
+ static picojson::value PayloadToJson(conv_payload_h payload);
+ private:
+ void UpdateListener(const int cur_listener_id);
+ static void ServiceListenerCb(conv_service_h service_handle,
+ conv_channel_h channel_handle,
+ conv_error_e error, conv_payload_h result, void* user_data);
+
+ protected:
+ std::vector<CallbackParam *> callback_param_gc_;
+};
+
+class ConvergenceAppCommunicationServerService : public ConvergenceAppCommunicationService {
+ public:
+ ConvergenceAppCommunicationServerService();
+ ConvergenceAppCommunicationServerService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceAppCommunicationServerService();
+ ConvergenceAppCommunicationServerService(const ConvergenceAppCommunicationServerService&) = delete;
+ ConvergenceAppCommunicationServerService(ConvergenceAppCommunicationServerService&&) = delete;
+ ConvergenceAppCommunicationServerService& operator=(const ConvergenceAppCommunicationServerService&) = delete;
+ ConvergenceAppCommunicationServerService& operator=(ConvergenceAppCommunicationServerService&&) = delete;
+
+ public:
+ virtual common::TizenResult Start(ConvergenceChannel *channel,
+ const int cur_listener_id);
+ virtual common::TizenResult Stop(ConvergenceChannel *channel,
+ const int cur_listener_id);
+};
+
+class ConvergenceAppCommunicationClientService : public ConvergenceAppCommunicationService {
+ public:
+ ConvergenceAppCommunicationClientService();
+ ConvergenceAppCommunicationClientService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceAppCommunicationClientService();
+ ConvergenceAppCommunicationClientService(const ConvergenceAppCommunicationClientService&) = delete;
+ ConvergenceAppCommunicationClientService(ConvergenceAppCommunicationClientService&&) = delete;
+ ConvergenceAppCommunicationClientService& operator=(const ConvergenceAppCommunicationClientService&) = delete;
+ ConvergenceAppCommunicationClientService& operator=(ConvergenceAppCommunicationClientService&&) = delete;
+ public:
+ common::TizenResult Connect(const int cur_listener_id);
+ common::TizenResult Disconnect();
+ private:
+ static void ServiceConnectedCb(conv_service_h service_handle,
+ conv_error_e error, conv_payload_h result, void* user_data);
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_channel.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Channel keys
+static const std::string kId = "id"; // This id is used in arguments (comes from JS layer)
+static const std::string kChannelId = "channel_id"; // This id is used in the App Comm Service engine
+static const std::string kUri = "uri";
+} // namespace
+
+ConvergenceChannel::ConvergenceChannel()
+ : channel_handle_(nullptr) {
+ ScopeLogger();
+}
+
+ConvergenceChannel::ConvergenceChannel(const picojson::value &channel_json)
+ : channel_handle_(nullptr) {
+ ScopeLogger();
+ FromJson(channel_json);
+}
+
+ConvergenceChannel::~ConvergenceChannel() {
+ ScopeLogger();
+
+ if (channel_handle_) {
+ conv_channel_destroy(channel_handle_);
+ channel_handle_ = NULL;
+ }
+}
+
+conv_channel_h ConvergenceChannel::GetHandle() const {
+ ScopeLogger();
+ return channel_handle_;
+}
+
+
+void ConvergenceChannel::FromJson(const picojson::value &channel_json) {
+ ScopeLogger();
+ if (channel_json.is<picojson::null>()) {
+ LoggerE("ERROR: Channel json value is NULL");
+ return;
+ }
+
+ if (channel_handle_) {
+ conv_channel_destroy(channel_handle_);
+ channel_handle_ = NULL;
+ }
+
+ int error = conv_channel_create(&channel_handle_);
+ if ((CONV_ERROR_NONE != error) || !channel_handle_) {
+ trace_conv_error(error, __LINE__, "creating channel handle");
+ return;
+ }
+
+ const std::string id = channel_json.get(kId).to_str();
+ error = conv_channel_set_string(channel_handle_, kChannelId.c_str(), id.c_str());
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "setting channel string Id");
+ }
+
+ const std::string uri = channel_json.get(kUri).to_str();
+ error = conv_channel_set_string(channel_handle_, kUri.c_str(), uri.c_str());
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "setting channel string URI");
+ }
+}
+
+picojson::value ConvergenceChannel::ToJson(conv_channel_h channel_handle) {
+ ScopeLogger();
+
+ picojson::object channel_object;
+ if (!channel_handle) {
+ LoggerE("Error: trying to convert NULL channel handle to json");
+ return picojson::value(channel_object);
+ }
+
+ { // Extracting channel ID
+ char *id = nullptr;
+ const int error = conv_channel_get_string(channel_handle, kChannelId.c_str(), &id);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "getting channel string Id");
+ } else {
+ channel_object[kId] = picojson::value(id);
+ free(id);
+ }
+ }
+
+ { // Extracting channel URI
+ char *uri = nullptr;
+ const int error = conv_channel_get_string(channel_handle, kUri.c_str(), &uri);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "getting channel string URI");
+ } else {
+ channel_object[kUri] = picojson::value(uri);
+ free(uri);
+ }
+ };
+
+ return picojson::value(channel_object);
+}
+
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_CHANNEL_H__
+#define CONVERGENCE_CONVERGENCE_CHANNEL_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceChannel {
+
+ public:
+ ConvergenceChannel();
+ ConvergenceChannel(const picojson::value &channel_json);
+ virtual ~ConvergenceChannel();
+ ConvergenceChannel(const ConvergenceChannel&) = delete;
+ ConvergenceChannel(ConvergenceChannel&&) = delete;
+ ConvergenceChannel& operator=(const ConvergenceChannel&) = delete;
+ ConvergenceChannel& operator=(ConvergenceChannel&&) = delete;
+
+ public:
+ conv_channel_h GetHandle() const;
+ void FromJson(const picojson::value &channel_json);
+
+ public:
+ static picojson::value ToJson(conv_channel_h channel_handle);
+
+ private:
+ conv_channel_h channel_handle_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_CHANNEL_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_client_info.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+#include <stdlib.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kIsHost = "client_is_host";
+static const std::string kConnectionTime = "client_connect_time"; //--
+static const std::string kClientId = "client_id";
+} // namespace
+
+ConvergenceClientInfo::ConvergenceClientInfo()
+ : isHost_(false)
+ , connectionTime_(0) {
+ ScopeLogger();
+}
+
+ConvergenceClientInfo::ConvergenceClientInfo(conv_payload_h payload)
+ : isHost_(false)
+ , connectionTime_(0) {
+ ScopeLogger();
+
+ isHost_ = ExtractPayloadString(payload, "client_is_host") == "1";
+ connectionTime_ = atol(ExtractPayloadString(payload, "client_connect_time").c_str());
+ clientId_ = ExtractPayloadString(payload, "client_id").c_str();
+}
+
+ConvergenceClientInfo::~ConvergenceClientInfo() {
+ ScopeLogger();
+}
+
+std::string ConvergenceClientInfo::ExtractPayloadString(conv_payload_h payload, const char *key) {
+ ScopeLogger();
+ char *value = nullptr;
+ const int error = conv_payload_get_string(payload, key, &value);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_payload_get_string");
+ return "";
+ }
+
+ if (value) {
+ const std::string result = std::string(value);
+ free(value);
+ return result;
+ }
+ return "";
+}
+
+picojson::value ConvergenceClientInfo::ToJson() const {
+ ScopeLogger();
+ picojson::object clientInfo;
+ clientInfo["isHost"] = picojson::value(static_cast<double>(isHost_));
+ clientInfo["connectionTime"] = picojson::value(static_cast<double>(connectionTime_));
+ clientInfo["clientId"] = picojson::value(clientId_);
+ return picojson::value(clientInfo);
+}
+
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
+#define CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceClientInfo {
+ public:
+ ConvergenceClientInfo();
+ ConvergenceClientInfo(conv_payload_h payload);
+ virtual ~ConvergenceClientInfo();
+ ConvergenceClientInfo(const ConvergenceClientInfo&) = delete;
+ ConvergenceClientInfo(ConvergenceClientInfo&&) = delete;
+ ConvergenceClientInfo& operator=(const ConvergenceClientInfo&) = delete;
+ ConvergenceClientInfo& operator=(ConvergenceClientInfo&&) = delete;
+
+ public:
+ picojson::value ToJson() const;
+
+ private:
+ std::string ExtractPayloadString(conv_payload_h payload, const char *key);
+
+ private:
+ bool isHost_;
+ std::string clientId_;
+ long connectionTime_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_device.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_remote_app_control_service.h"
+#include "convergence/convergence_app_communication_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kId = "id";
+static const std::string kName = "name"; //--
+static const std::string kDeviceType = "profile";
+static const std::string kDeviceServices = "services";
+} // namespace
+
+ConvergenceDevice::ConvergenceDevice()
+ : device_handle_(nullptr)
+ , convergence_plugin_(NULL) {
+ ScopeLogger();
+}
+
+ConvergenceDevice::ConvergenceDevice(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : device_handle_(device)
+ , convergence_plugin_(convergence_plugin) {
+ ScopeLogger();
+}
+
+ConvergenceDevice::~ConvergenceDevice() {
+ ScopeLogger();
+
+ // Releasing all registered services
+ for (auto it = services_.begin(); it != services_.end(); ++it) {
+ delete it->second;
+ }
+ services_.clear();
+
+ conv_device_destroy(device_handle_);
+}
+
+std::string ConvergenceDevice::ExtractDevicePropery(const char *property) {
+ ScopeLogger();
+ char *value = nullptr;
+ const int error = conv_device_get_property_string(device_handle_, property, &value);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_device_get_property_string");
+ return "";
+ }
+
+ if (value) {
+ const std::string result = std::string(value);
+ free(value);
+ return result;
+ }
+ return "";
+}
+
+ConvergenceService *ConvergenceDevice::SwapService(const int service_type) {
+ ScopeLogger();
+ LoggerI("Swapping service of type [%d]", service_type);
+ if (services_.count(service_type) <= 0) {
+ switch(service_type) {
+ case CONV_SERVICE_APP_TO_APP_COMMUNICATION: {
+ services_[service_type] =
+ new ConvergenceAppCommunicationService(device_handle_,
+ convergence_plugin_);
+ break;
+ }
+ case CONV_SERVICE_REMOTE_APP_CONTROL: {
+ LoggerI("Adding Remote App Control service");
+ services_[service_type] =
+ new ConvergenceRemoteAppControlService(device_handle_,
+ convergence_plugin_);
+ break;
+ }
+ default: {
+ LoggerE("ERROR! UNKNOWN SERVICE TYPE [%d]", service_type);
+ return nullptr;
+ }
+ }
+ }
+ return services_[service_type];
+}
+
+ConvergenceService *ConvergenceDevice::RegisterLocalService(const int service_type) {
+ ScopeLogger();
+ LoggerI("Registering the local service of type [%d]", service_type);
+ if (services_.count(service_type) <= 0) {
+ switch(service_type) {
+ case CONV_SERVICE_APP_TO_APP_COMMUNICATION: {
+ services_[service_type] =
+ new ConvergenceAppCommunicationServerService(device_handle_,
+ convergence_plugin_);
+ LoggerI("Registered for local device [%s] the service [0x%0x] of type [%d]",
+ id_.c_str(), services_[service_type], CONV_SERVICE_APP_TO_APP_COMMUNICATION);
+ break;
+ }
+ default: {
+ LoggerE("ERROR! UNKNOWN SERVICE TYPE [%d]", service_type);
+ return nullptr;
+ }
+ }
+ }
+ return services_[service_type];
+}
+
+void ConvergenceDevice::ForEachServiceCb(conv_service_h service_handle,
+ void* user_data) {
+ ScopeLogger();
+ if (!service_handle || !user_data) {
+ LoggerE("ERROR! Invalid parameters of D2D API Callback");
+ return;
+ }
+ ConvergenceDevice *owner = static_cast<ConvergenceDevice *>(user_data);
+
+ // Extracting service type
+ conv_service_e type = CONV_SERVICE_NONE;
+ int error = conv_service_get_type(service_handle, &type);
+ if (CONV_ERROR_NONE != error) {
+ LoggerE("ERROR! D2D API Get Service Type error [%d]", error);
+ return;
+ }
+
+ ConvergenceService *s = owner->SwapService(type);
+ if (!s) {
+ LoggerE("ERROR! Cannot add NULL service");
+ return;
+ }
+
+ s->Refresh();
+}
+
+void ConvergenceDevice::Refresh() {
+ ScopeLogger();
+ // Getting device properties from handle
+ id_ = ExtractDevicePropery(CONV_DEVICE_ID);
+ name_ = ExtractDevicePropery(CONV_DEVICE_NAME);
+ type_ = ExtractDevicePropery(CONV_DEVICE_TYPE);
+
+ LoggerE("Refreshed device id [%s] name [%s] type [%s]",
+ id_.c_str(), name_.c_str(), type_.c_str());
+
+ // Extracting services
+ const int error = conv_device_foreach_service(device_handle_, ForEachServiceCb, this);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_device_foreach_service");
+ }
+}
+
+picojson::value ConvergenceDevice::ToJson() const {
+ ScopeLogger();
+ picojson::object device_json;
+
+ // Convert device props and services into JSON
+ device_json[kId] = picojson::value(id_);
+ device_json[kName] = picojson::value(name_);
+ device_json[kDeviceType] = picojson::value(type_);
+
+ picojson::array services;
+ for (auto it = services_.begin(); it != services_.end(); ++it) {
+ ConvergenceService *s = it->second;
+ services.push_back(s->ToJson());
+ }
+ device_json[kDeviceServices] = picojson::value(services);
+
+ return picojson::value(device_json);
+}
+
+ConvergenceService *ConvergenceDevice::GetService(const int service_type) const {
+ ScopeLogger();
+ if (services_.count(service_type) <= 0)
+ return nullptr;
+ else
+ return services_[service_type];
+}
+
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_DEVICE_H__
+#define CONVERGENCE_CONVERGENCE_DEVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceInstance;
+class ConvergenceService;
+
+class ConvergenceDevice {
+
+ public:
+ ConvergenceDevice();
+ ConvergenceDevice(conv_device_h device_handle, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceDevice();
+ ConvergenceDevice(const ConvergenceDevice&) = delete;
+ ConvergenceDevice(ConvergenceDevice&&) = delete;
+ ConvergenceDevice& operator=(const ConvergenceDevice&) = delete;
+ ConvergenceDevice& operator=(ConvergenceDevice&&) = delete;
+
+
+ public:
+ void Refresh();
+ ConvergenceService *GetService(const int service_type) const;
+ //picojson::object ToJson() const;
+ picojson::value ToJson() const;
+ //std::string get_device() const {return device_handle_; }
+
+ public:
+ ConvergenceService *RegisterLocalService(const int service_type);
+ void SetId(const std::string &id) { id_ = id; }
+
+ private:
+ ConvergenceService *SwapService(const int service_type);
+ std::string ExtractDevicePropery(const char *property);
+ static void ForEachServiceCb(conv_service_h service_handle, void* user_data);
+
+ private:
+ conv_device_h device_handle_;
+ ConvergenceInstance *convergence_plugin_;
+ mutable std::unordered_map<int, ConvergenceService *> services_;
+
+ private:
+ std::string id_;
+ std::string name_;
+ std::string type_; // Device profile: mobile, wearable, TV
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_DEVICE_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "convergence/convergence_extension.h"
+
+#include "convergence/convergence_instance.h"
+
+// This will be generated from convergence_api.js
+extern const char kSource_convergence_api[];
+
+common::Extension* CreateExtension() {
+ return new ConvergenceExtension;
+}
+
+ConvergenceExtension::ConvergenceExtension() {
+ SetExtensionName("tizen.convergence");
+ SetJavaScriptAPI(kSource_convergence_api);
+
+ const char* entry_points[] = {
+ "tizen.RemoteAppControlService",
+ "tizen.AppCommunicationServerService",
+ "tizen.AppCommunicationClientService",
+ "tizen.Channel",
+ "tizen.PayloadString",
+ "tizen.PayloadRawBytes",
+ nullptr
+ };
+ SetExtraJSEntryPoints(entry_points);
+}
+
+ConvergenceExtension::~ConvergenceExtension() {}
+
+common::Instance* ConvergenceExtension::CreateInstance() {
+ return new extension::convergence::ConvergenceInstance;
+}
* limitations under the License.
*/
-#ifndef SECUREELEMENT_READER_H_
-#define SECUREELEMENT_READER_H_
+#ifndef CONVERGENCE_CONVERGENCE_EXTENSION_H_
+#define CONVERGENCE_CONVERGENCE_EXTENSION_H_
-#include "common/picojson.h"
-#include <Reader.h>
+#include "common/extension.h"
-namespace extension {
-namespace secureelement {
+class ConvergenceExtension : public common::Extension {
+ public:
+ ConvergenceExtension();
+ virtual ~ConvergenceExtension();
-class SEReader {
-public:
- SEReader(smartcard_service_api::Reader* reader_ptr) : m_reader(reader_ptr) {};
- ~SEReader() {};
-
- picojson::value getName();
- picojson::value isPresent();
- picojson::value openSession();
- void closeSessions();
-private:
- smartcard_service_api::Reader* m_reader;
+ private:
+ virtual common::Instance* CreateInstance();
};
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_READER_H_
+#endif // CONVERGENCE_CONVERGENCE_EXTENSION_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "convergence/convergence_instance.h"
+
+#include <functional>
+#include <string>
+
+#include "convergence/convergence_manager.h"
+#include "convergence/convergence_remote_app_control_service.h"
+#include "convergence/convergence_app_communication_service.h"
+#include "convergence/convergence_channel.h"
+#include "convergence/convergence_payload.h"
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/task-queue.h"
+#include "common/tools.h"
+
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// The privileges that required in Convergence API
+const std::string kPrivilegeInternet = "http://tizen.org/privilege/internet";
+const std::string kPrivilegeBluetooth = "http://tizen.org/privilege/bluetooth";
+const std::string kPrivilegeWifiDirect = "http://tizen.org/privilege/wifidirect";
+
+// JS listener keys
+static const std::string kJSListenerStatus = "status";
+static const std::string kJSCurrentListenerId = "curListenerId";
+static const std::string kJSTargetListenerId = "listenerId";
+static const std::string kSuccess = "success";
+static const std::string kError = "error";
+
+// Arguments, passed from JS
+static const std::string kJSCallbackId = "callbackId";
+static const std::string kJSArgumentDeviceId = "deviceId";
+static const std::string kJSArgumentServiceTypeNumber = "serviceTypeNumber";
+static const std::string kJSArgumentChannel = "channel_data";
+static const std::string kJSArgumentPayload = "payload";
+static const std::string kJSArgumentAppId = "appId";
+static const std::string kJSArgumentReply = "reply";
+static const std::string kJSArgumentTimeout = "timeout";
+static const std::string kJSArgumentService = "service";
+} // namespace
+
+using namespace common;
+
+ConvergenceInstance::ConvergenceInstance() {
+ using namespace std::placeholders;
+ #define REGISTER_SYNC(c,x) \
+ RegisterSyncHandler(c, std::bind(&ConvergenceInstance::x, this, _1, _2));
+ REGISTER_SYNC("ConvergenceManager_stopDiscovery",
+ ConvergenceManagerStopDiscovery);
+
+ REGISTER_SYNC("AppCommunicationService_addListener", AppCommunicationServiceAddListener);
+ REGISTER_SYNC("AppCommunicationService_removeListener", AppCommunicationServiceRemoveListener);
+ //REGISTER_SYNC("Service_createLocalService", ServiceCreateLocal);
+ #undef REGISTER_SYNC
+ #define REGISTER_ASYNC(c,x) \
+ RegisterSyncHandler(c, std::bind(&ConvergenceInstance::x, this, _1, _2));
+ REGISTER_ASYNC("ConvergenceManager_startDiscovery",
+ ConvergenceManagerStartDiscovery);
+
+ REGISTER_ASYNC("RemoteAppControlService_connect", RemoteAppControlServiceConnect);
+ REGISTER_ASYNC("RemoteAppControlService_disconnect", RemoteAppControlServiceDisconnect);
+ REGISTER_ASYNC("RemoteAppControlService_launch", RemoteAppControlServiceLaunch);
+
+ REGISTER_ASYNC("AppCommunicationService_start", AppCommunicationServiceStart);
+ REGISTER_ASYNC("AppCommunicationService_stop", AppCommunicationServiceStop);
+ REGISTER_ASYNC("AppCommunicationService_send", AppCommunicationServiceSend);
+
+ REGISTER_ASYNC("AppCommunicationServerService_constructLocal", AppCommunicationServerServiceConstructLocal);
+
+ REGISTER_ASYNC("AppCommunicationClientService_connect", AppCommunicationClientServiceConnect);
+ REGISTER_ASYNC("AppCommunicationClientService_disconnect", AppCommunicationClientServiceDisconnect);
+ #undef REGISTER_ASYNC
+}
+
+ConvergenceInstance::~ConvergenceInstance() {
+}
+
+void ConvergenceInstance::ReplyAsync(ConvergenceCallbacks callback_function_type,
+ int curListenerId, bool isSuccess, picojson::object& param) {
+ ScopeLogger();
+
+ param[kJSListenerStatus] = picojson::value(isSuccess ? kSuccess : kError);
+ param[kJSCurrentListenerId] = picojson::value(static_cast<double>(curListenerId));
+
+ switch(callback_function_type) {
+ case kConvergenceManagerDiscoveryCallback: {
+ param[kJSTargetListenerId] = picojson::value("CONVERGENCE_DISCOVERY_LISTENER");
+ break;
+ }
+ /*case kRemoteAppControlServiceConnectCallback: {
+ param[kJSTargetListenerId] =
+ picojson::value("REMOTE_APP_CONTROL_SERVICE_CONNECT_LISTENER");
+ break;
+ }*/
+ case kRemoteAppControlListenerCallback: {
+ param[kJSTargetListenerId] =
+ picojson::value("REMOTE_APP_CONTROL_SERVICE_LISTENER");
+ break;
+ }
+ /*case kAppCommunicationSuccessCallback: {
+ param[kJSTargetListenerId] =
+ picojson::value("APP_COMMUNICATION_SERVICE_SUCCESS_LISTENER");
+ break;
+ }*/
+ case kAppCommunicationListenerCallback: {
+ param[kJSTargetListenerId] =
+ picojson::value("APP_COMMUNICATION_SERVICE_LISTENER");
+ break;
+ }
+ /*case kAppCommunicationClientServiceConnectCallback: {
+ param[kJSTargetListenerId] =
+ picojson::value("APP_COMMUNICATON_CLIENT_SERVICE_CONNECT_LISTENER");
+ break;
+ }*/
+ default: {
+ LoggerE("Invalid Callback Type");
+ return;
+ }
+ }
+
+ picojson::value result = picojson::value(param);
+ LoggerD("---> %s", result.serialize().c_str()); // TODO remove
+
+ PostMessage(result.serialize().c_str());
+}
+
+#define CHECK_EXIST(args, name, out) \
+ if (!args.contains(name)) {\
+ ReportError(TypeMismatchException(name" is required argument"), out);\
+ return;\
+ }
+
+void ConvergenceInstance::ConvergenceManagerStartDiscovery(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+ CHECK_EXIST(args, "timeout", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ LoggerI("ARGS: %s", args.serialize().c_str());
+
+ auto start_discovery =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("start_discovery");
+
+ // Start the discovery procedure
+ ConvergenceManager::GetInstance(this).StartDiscovery(
+ static_cast<long>(args.get(kJSArgumentTimeout).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto start_discovery_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("start_discovery_result");
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ start_discovery,
+ start_discovery_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::ConvergenceManagerStopDiscovery(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ // Running the discovery stop procedure
+ ConvergenceManager::GetInstance(this).StopDiscovery();
+ //out[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceConnect(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ LoggerI("ARGS: %s", args.serialize().c_str());
+
+ auto connect =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("connect");
+
+ // Finding the service
+ ConvergenceRemoteAppControlService *service =
+ static_cast<ConvergenceRemoteAppControlService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_REMOTE_APP_CONTROL));
+ if (!service) {
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ //ReportSuccess(object); // TODO ReportError
+ return;
+ }
+
+ // Running the service connect procedure
+ service->Connect(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto connect_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("connect_result");
+
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ connect,
+ connect_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceDisconnect(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ //LoggerI("ARGS: %s", args.serialize().c_str());
+
+ auto disconnect =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("disconnect");
+
+ // Finding the service
+ ConvergenceRemoteAppControlService *service =
+ static_cast<ConvergenceRemoteAppControlService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_REMOTE_APP_CONTROL));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service disconnect procedure
+ service->Disconnect();
+
+ picojson::object& object = result->get<picojson::object>();
+ ReportSuccess(object);
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Async<picojson::value>(
+ disconnect,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceLaunch(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ auto launch = [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("send");
+
+ // Finding the service
+ ConvergenceRemoteAppControlService *service =
+ static_cast<ConvergenceRemoteAppControlService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_REMOTE_APP_CONTROL));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service app control procedure
+ service->Launch(
+ args.get(kJSArgumentAppId).to_str().c_str(),
+ static_cast<bool>(args.get(kJSArgumentReply).get<bool>()),
+ static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto launch_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("send_result");
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ launch,
+ launch_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceStart(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ auto start = [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("start");
+
+ // Finding the service
+ ConvergenceAppCommunicationService *service =
+ static_cast<ConvergenceAppCommunicationService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 0, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service start procedure
+ service->Start(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+ static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto start_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("start_result");
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ start,
+ start_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceSend(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ auto send = [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("send");
+
+ // Finding the service
+ ConvergenceAppCommunicationService *service =
+ static_cast<ConvergenceAppCommunicationService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 0, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service send procedure
+ service->Send(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+ new ConvergencePayloadArray(args.get(kJSArgumentPayload)),
+ static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto send_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("send_result");
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ send,
+ send_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceStop(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ auto stop = [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("stop");
+
+ // Finding the service
+ ConvergenceAppCommunicationService *service =
+ static_cast<ConvergenceAppCommunicationService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 0, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service stop procedure
+ service->Stop(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+ static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto stop_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("stop_result");
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ stop,
+ stop_result,
+ data);
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceAddListener(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ LoggerI("ARGS: %s", args.serialize().c_str());
+
+ // Finding the service
+ ConvergenceAppCommunicationService *service =
+ static_cast<ConvergenceAppCommunicationService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 0, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service stop procedure
+ service->SetListener(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceRemoveListener(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ // Finding the service
+ ConvergenceAppCommunicationService *service =
+ static_cast<ConvergenceAppCommunicationService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 0, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service stop procedure
+ service->RemoveListener();
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServerServiceConstructLocal(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ // Finding the service
+ ConvergenceAppCommunicationClientService *service =
+ static_cast<ConvergenceAppCommunicationClientService *>(
+ ConvergenceManager::GetInstance(this).RegisterLocalService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationClientServiceConnect(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ CHECK_EXIST(args, "callbackId", out)
+
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ LoggerI("ARGS: %s", args.serialize().c_str());
+
+ auto connect =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("connect");
+
+ // Finding the service
+ ConvergenceAppCommunicationClientService *service =
+ static_cast<ConvergenceAppCommunicationClientService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ //ReportSuccess(object); // TODO ReportError
+ return;
+ }
+
+ // Running the service connect procedure
+ service->Connect(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+ picojson::object& object = result->get<picojson::object>();
+ object[kJSCallbackId] = args.get(kJSCallbackId);
+ ReportSuccess(object);
+ };
+
+ auto connect_result =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("connect_result");
+
+ result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+ Instance::PostMessage(this, result->serialize().c_str());
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ connect,
+ connect_result,
+ data);
+ ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationClientServiceDisconnect(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+ //LoggerI("ARGS: %s", args.serialize().c_str());
+
+ auto disconnect =
+ [this, args](const std::shared_ptr<picojson::value>& result) {
+ ScopeLogger("disconnect");
+
+ // Finding the service
+ ConvergenceAppCommunicationClientService *service =
+ static_cast<ConvergenceAppCommunicationClientService *>(
+ ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+ CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+ if (!service) {
+ //ReportSuccess(object); // TODO ReportError
+ LoggerE("Can not find the service type = 1, device_id = ",
+ args.get(kJSArgumentDeviceId).to_str().c_str());
+ return;
+ }
+
+ // Running the service disconnect procedure
+ service->Disconnect();
+
+ picojson::object& object = result->get<picojson::object>();
+ ReportSuccess(object);
+ };
+
+ auto data =
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+ TaskQueue::GetInstance().Async<picojson::value>(
+ disconnect,
+ data);
+ ReportSuccess(out);
+}
+
+
+#undef CHECK_EXIST
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_INSTANCE_H_
+#define CONVERGENCE_CONVERGENCE_INSTANCE_H_
+
+//#include "common/tizen_instance.h"
+#include "common/extension.h"
+
+namespace extension {
+namespace convergence {
+
+enum ConvergenceCallbacks {
+ // Convergence Manager Discovery
+ kConvergenceManagerDiscoveryCallback,
+
+ // Remote App Control
+ //kRemoteAppControlServiceConnectCallback,
+ kRemoteAppControlListenerCallback,
+
+ // App Communication
+ //kAppCommunicationSuccessCallback,
+ kAppCommunicationListenerCallback,
+
+
+ // App Communication Client
+ //kAppCommunicationClientServiceConnectCallback
+};
+
+
+// TODO: inherit it by common::TizenInstance class
+//class ConvergenceInstance : public common::TizenInstance {
+
+class ConvergenceInstance : public common::ParsedInstance {
+ public:
+ ConvergenceInstance();
+ virtual ~ConvergenceInstance();
+ public:
+ void ReplyAsync(ConvergenceCallbacks cbfunc,
+ int curListenerId, bool isSuccess, picojson::object& param);
+
+ private:
+ // TODO: make all API functions return common::TizenResult
+
+ // Convergence Manager
+ void ConvergenceManagerStartDiscovery(const picojson::value& args,
+ picojson::object& out);
+ void ConvergenceManagerStopDiscovery(const picojson::value& args,
+ picojson::object& out);
+
+ // Remote App Control Service
+ void RemoteAppControlServiceConnect(const picojson::value& args, picojson::object& out);
+ void RemoteAppControlServiceDisconnect(const picojson::value& args, picojson::object& out);
+ void RemoteAppControlServiceLaunch(const picojson::value& args, picojson::object& out);
+
+ // App Communication Service
+ void AppCommunicationServiceStart(const picojson::value& args, picojson::object& out);
+ void AppCommunicationServiceStop(const picojson::value& args, picojson::object& out);
+ void AppCommunicationServiceSend(const picojson::value& args, picojson::object& out);
+ void AppCommunicationServiceAddListener(const picojson::value& args, picojson::object& out);
+ void AppCommunicationServiceRemoveListener(const picojson::value& args, picojson::object& out);
+
+ // App Communication Server Service
+ void AppCommunicationServerServiceConstructLocal(const picojson::value& args, picojson::object& out);
+
+ // App Communication Client Service
+ void AppCommunicationClientServiceConnect(const picojson::value& args, picojson::object& out);
+ void AppCommunicationClientServiceDisconnect(const picojson::value& args, picojson::object& out);
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_INSTANCE_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "convergence/convergence_manager.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_device.h"
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+
+// TODO check which fields are needed
+// TODO remove dublications, marked with //---
+namespace {
+// Commonly used key words
+static const std::string kId = "id"; //---
+static const std::string kName = "name"; //--
+static const std::string kKey = "key";
+static const std::string kValue = "value";
+
+// Channel data keys
+static const std::string kChannel = "channel";
+static const std::string kChannelDataChannelId = "channel_id";
+static const std::string kChannelDataChannelOption = "option";
+static const std::string kChannelDataChannelOptions = "options";
+
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+static const std::string kPayloadDataType = "type"; // String, bytes or app control
+static const std::string kTypeString = "STRING";
+static const std::string kTypeRawBytes = "RAW_BYTES";
+static const std::string kTypeAppControl = "APP_CONTROL";
+static const std::string kPayloadDataAppControlAppId = "appI";
+static const std::string kPayloadDataAppControlOperation = "operation";
+static const std::string kPayloadDataAppControlUri = "uri";
+static const std::string kPayloadDataAppControlMime = "mime";
+static const std::string kPayloadDataAppControlLaunchMode = "launch_mode";
+static const std::string kPayloadDataAppControlCategory = "category";
+
+// Service keys
+static const std::string kServiceType = "serviceType"; //---
+static const std::string kServiceConnectionState = "connectionState"; //---
+static const std::string kServiceProperties = "properties";
+
+// Device keys
+static const std::string kDevice = "device";
+static const std::string kDeviceType = "profile"; //---
+static const std::string kDeviceServices = "services"; //---
+
+// Discovery keys
+static const std::string kDiscoveryStatus = "discovery_status";
+static const std::string kDiscoveryStatusDeviceFound = "device_found";
+static const std::string kDiscoveryStatusFinished = "discovery_finished";
+static const std::string kDiscoveryStatusError = "discovery_error";
+static const std::string kDiscoveryError = "discovery_error";
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; //---
+static const std::string kServiceConnectionStatusConnected = "service_connected"; //---
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected"; //---
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+ConvergenceManager &ConvergenceManager::GetInstance(
+ ConvergenceInstance *owner) {
+ static ConvergenceManager instance;
+ instance.convergence_plugin_ = owner;
+ return instance;
+}
+
+ConvergenceManager::ConvergenceManager()
+ : convergence_plugin_(nullptr)
+ , convergence_manager_(nullptr) {
+ ScopeLogger();
+ const int error = conv_create(&convergence_manager_);
+ if (CONV_ERROR_NONE != error) {
+ // Handle error
+ trace_conv_error(error, __LINE__, "conv_create");
+ }
+}
+
+ConvergenceManager::~ConvergenceManager() {
+ ScopeLogger();
+
+ // Releasing all registered devices
+ for (auto it = registered_devices_.begin(); it != registered_devices_.end(); ++it) {
+ delete it->second;
+ }
+ registered_devices_.clear();
+
+ int error = conv_destroy(convergence_manager_);
+ if (CONV_ERROR_NONE != error) {
+ // Handle error
+ trace_conv_error(error, __LINE__, "conv_destroy");
+ }
+ convergence_manager_ = nullptr;
+}
+
+ConvergenceDevice *ConvergenceManager::SwapDevice(const char *device_id,
+ conv_device_h device_handle) {
+ ScopeLogger();
+ if (registered_devices_.count(device_id) <= 0) {
+ ConvergenceDevice *d = new ConvergenceDevice(device_handle, convergence_plugin_);
+ d->SetId(device_id);
+ registered_devices_[device_id] = d;
+ LoggerI("...registering the device [%s, %x]", device_id, device_handle);
+ }
+ return registered_devices_[device_id];
+}
+
+void ConvergenceManager::DiscoveryCb(conv_device_h device_handle,
+ conv_discovery_result_e result, void* user_data) {
+ ScopeLogger();
+
+ if (!user_data) {
+ LoggerE("ERROR! NULL user data in discovery callback");
+ return;
+ }
+
+ ConvergenceManager *owner = static_cast<ConvergenceManager *>(user_data);
+
+ switch(result) {
+ case CONV_DISCOVERY_RESULT_SUCCESS: {
+ LoggerI("...found a device");
+
+ char *id = nullptr;
+ int error = conv_device_get_property_string(device_handle, CONV_DEVICE_ID, &id);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_device_get_property_string ID");
+ }
+ if (!id) {
+ LoggerE("BAD ERROR: Device ID is NULL");
+ return; // TODO report error
+ }
+
+ conv_device_h clone_device = nullptr;
+ error = conv_device_clone(device_handle, &clone_device);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_device_clone");
+ break;
+ }
+ ConvergenceDevice *d = owner->SwapDevice(id, clone_device);
+ free(id);
+
+ if (!d) {
+ // Handle bad error
+ LoggerE("BAD ERROR: Cannot swap the device");
+ break;
+ }
+
+ d->Refresh();
+
+ picojson::object param;
+ param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusDeviceFound);
+ param[kDevice] = d->ToJson();
+ owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+ -1,
+ true,
+ param);
+
+ break;
+ }
+ case CONV_DISCOVERY_RESULT_FINISHED: {
+ LoggerE("...discovery finished");
+
+ picojson::object param;
+ param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusFinished);
+ owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+ -1,
+ true,
+ param);
+ break;
+ }
+ case CONV_DISCOVERY_RESULT_ERROR: {
+ LoggerE("Discovery Error");
+ picojson::object param;
+ param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusError);
+ param[kDiscoveryError] = picojson::value(static_cast<double>(result));
+ owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+ -1,
+ false,
+ param);
+ break;
+ }
+ default: {
+ LoggerE("Unknown discovery result");
+ break;
+ }
+ }
+}
+
+TizenResult ConvergenceManager::StartDiscovery(long timeout) {
+ ScopeLogger();
+ const int error = conv_discovery_start(convergence_manager_,
+ (const int)timeout, DiscoveryCb, this);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_discovery_start");
+ }
+ return TizenSuccess();
+}
+
+TizenResult ConvergenceManager::StopDiscovery() {
+ ScopeLogger();
+ const int error = conv_discovery_stop(convergence_manager_);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_discovery_stop");
+ }
+ return TizenSuccess();
+}
+
+//-------------
+// TODO Implement the NULL Object pattern for Service,
+// so this function would return always valid pointers
+//-------------
+ConvergenceService *ConvergenceManager::GetService(const char *device_id,
+ const int service_type) const {
+ ScopeLogger();
+
+ LoggerI("Getting the service object for id [%s], type [%d]", device_id, service_type);
+ if (registered_devices_.count(device_id) <= 0) {
+ LoggerE("Device ID not found");
+ return nullptr;
+ }
+
+ ConvergenceDevice *d = registered_devices_[device_id];
+ if (!d) {
+ LoggerE("Device object not found");
+ return nullptr;
+ }
+
+ return d->GetService(service_type);
+}
+
+ConvergenceService *ConvergenceManager::RegisterLocalService(const char *device_id,
+ const int service_type) {
+ ScopeLogger();
+
+ LoggerI("Registering local service [%d] for device id [%s]", service_type, device_id);
+
+ ConvergenceDevice *d = SwapDevice(device_id, nullptr);
+ if (!d) {
+ LoggerE("Device object not found");
+ return nullptr;
+ }
+
+ return d->RegisterLocalService(service_type);
+}
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_MANAGER_H__
+#define CONVERGENCE_CONVERGENCE_MANAGER_H__
+
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+
+class ConvergenceDevice;
+class ConvergenceService;
+
+// TODO rename to Discovery Manager
+// TODO extract service start, stop, read, send to Service Manager class
+class ConvergenceManager {
+
+ public:
+ static ConvergenceManager &GetInstance(class ConvergenceInstance *owner);
+
+ public:
+ ConvergenceManager();
+ ~ConvergenceManager();
+ ConvergenceManager(const ConvergenceManager&) = delete;
+ ConvergenceManager(ConvergenceManager&&) = delete;
+ ConvergenceManager& operator=(const ConvergenceManager&) = delete;
+ ConvergenceManager& operator=(ConvergenceManager&&) = delete;
+
+ public:
+ common::TizenResult StartDiscovery(long timeout);
+ common::TizenResult StopDiscovery();
+
+ public:
+ ConvergenceService *GetService(const char *device_id,
+ const int service_type) const;
+ ConvergenceService *RegisterLocalService(const char *device_id,
+ const int service_type);
+
+ private:
+ static void DiscoveryCb(conv_device_h device_handle,
+ conv_discovery_result_e result, void* user_data);
+ ConvergenceDevice *SwapDevice(const char *device_id,
+ conv_device_h device_handle);
+
+ private:
+ class ConvergenceInstance *convergence_plugin_;
+ conv_h convergence_manager_;
+ mutable std::unordered_map<std::string, ConvergenceDevice *> registered_devices_; // TODO rename to discovered_devices_ or simply devices_
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_MANAGER_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_payload.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Payload data keys and some values
+static const std::string kKey = "key";
+static const std::string kValue = "value";
+static const std::string kPayloadDataType = "type"; // String, bytes
+static const std::string kTypeString = "STRING";
+static const std::string kTypeRawBytes = "RAW_BYTES";
+} // namespace
+
+ConvergencePayloadArray::ConvergencePayloadArray()
+ : payload_handle_(nullptr) {
+ ScopeLogger();
+}
+
+ConvergencePayloadArray::ConvergencePayloadArray(const picojson::value &payload_json)
+ : payload_handle_(nullptr) {
+ ScopeLogger();
+ FromJson(payload_json);
+}
+
+ConvergencePayloadArray::~ConvergencePayloadArray() {
+ ScopeLogger();
+
+ if (payload_handle_) {
+ conv_payload_destroy(payload_handle_);
+ payload_handle_ = nullptr;
+ }
+}
+
+conv_payload_h ConvergencePayloadArray::GetHandle() const {
+ ScopeLogger();
+ return payload_handle_;
+}
+
+
+void ConvergencePayloadArray::FromJson(const picojson::value &payload_json) {
+ ScopeLogger();
+ if (payload_json.is<picojson::null>()) {
+ LoggerE("ERROR: trying to convert NULL payload json value");
+ return;
+ }
+
+ if (payload_handle_) {
+ conv_payload_destroy(payload_handle_);
+ payload_handle_ = nullptr;
+ }
+
+ int error = conv_payload_create(&payload_handle_);
+ if ((CONV_ERROR_NONE != error) || !payload_handle_) {
+ trace_conv_error(error, __LINE__, "creating payload handle");
+ return;
+ }
+
+ if (!payload_json.is<picojson::array>()) {
+ LoggerE("ERROR: Payload json is not an array");
+ return;
+ }
+
+ const picojson::array &payload_items = payload_json.get<picojson::array>();
+ for (size_t i = 0; i < payload_items.size(); i++) {
+ picojson::value item = payload_items[i];
+ const std::string type = item.get(kPayloadDataType).to_str();
+ if (kTypeString == type) {
+ const std::string key = item.get(kKey).to_str();
+ const std::string value = item.get(kValue).to_str(); // TODO: check if it is an object
+ int error = conv_payload_set_string(payload_handle_, key.c_str(), value.c_str());
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "setting payload string");
+ }
+ } else if (kTypeRawBytes == type) {
+ // TODO
+ LoggerW("IMPLEMENT BYTE PAYLOAD!!!");
+ } else {
+ LoggerE("ERROR! Unknown type of payload [%s]", type.c_str());
+ }
+ }
+}
+
+picojson::value ConvergencePayloadArray::ToJson(conv_payload_h payload_handle) {
+ ScopeLogger();
+
+ picojson::array payloads; // Array of payloads to deliver to JS layer
+
+ do {
+ if (!payload_handle) {
+ LoggerE("ERROR: trying to convert NULL payload handle to json");
+ break;
+ }
+
+ picojson::value parsed_payload;
+ {
+ char *payload_json_str = nullptr;
+ int error = conv_payload_internal_export_to_string(payload_handle, &payload_json_str);
+ if ((CONV_ERROR_NONE != error) || !payload_json_str) {
+ trace_conv_error(error, __LINE__, "converting payload handle to json");
+ break;
+ }
+
+ std::string err;
+ picojson::parse(parsed_payload, payload_json_str,
+ payload_json_str + strlen(payload_json_str), &err);
+ free(payload_json_str);
+ if (!err.empty()) {
+ LoggerE("Error parsing payload json: %s", err.c_str());
+ break;
+ }
+ }
+
+ if (!parsed_payload.is<picojson::object>()) {
+ LoggerE("ERROR: Payload is not an object");
+ break;
+ }
+
+ const picojson::object &payload_items = parsed_payload.get<picojson::object>();
+ for (auto it = std::begin(payload_items); it != std::end(payload_items); ++it) {
+ const std::string item_name = it->first;
+ const picojson::value item_value = it->second;
+
+ picojson::object payload_object;
+ payload_object[kKey] = picojson::value(item_name);
+
+ // Recognizing type of the payload
+ if (item_value.is<picojson::array>()) { // Byte array payload
+ payload_object[kPayloadDataType] = picojson::value(kTypeRawBytes);
+ payload_object[kValue] = item_value;
+ } else { // String payload
+ payload_object[kPayloadDataType] = picojson::value(kTypeString);
+ payload_object[kValue] = item_value;
+ }
+
+ payloads.push_back(picojson::value(payload_object));
+ }
+ } while(false);
+
+ return picojson::value(payloads);
+}
+
+std::string ConvergencePayloadArray::ExtractPayloadString(conv_payload_h payload, const char *key) {
+ ScopeLogger();
+ char *value = nullptr;
+ const int error = conv_payload_get_string(payload, key, &value);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_payload_get_string");
+ return "";
+ }
+
+ if (value) {
+ const std::string result = std::string(value);
+ free(value);
+ return result;
+ }
+ return "";
+}
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_PAYLOAD_H__
+#define CONVERGENCE_CONVERGENCE_PAYLOAD_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+
+/*enum ConvergencePayloadType {
+ kUnknownPayload = -1,
+ kStringPayload,
+ kRawBytesPayload
+};*/
+
+
+// TODO rename to simply Payload
+class ConvergencePayloadArray {
+ public:
+ ConvergencePayloadArray();
+ ConvergencePayloadArray(const picojson::value &payload_json);
+ virtual ~ConvergencePayloadArray();
+ ConvergencePayloadArray(const ConvergencePayloadArray&) = delete;
+ ConvergencePayloadArray(ConvergencePayloadArray&&) = delete;
+ ConvergencePayloadArray& operator=(const ConvergencePayloadArray&) = delete;
+ ConvergencePayloadArray& operator=(ConvergencePayloadArray&&) = delete;
+
+ public:
+ conv_payload_h GetHandle() const;
+ void FromJson(const picojson::value &payload_json);
+
+ public:
+ static picojson::value ToJson(conv_payload_h payload_handle);
+ static std::string ExtractPayloadString(conv_payload_h payload, const char *key);
+
+ private:
+ conv_payload_h payload_handle_;
+};
+
+/*
+class ConvergencePayload {
+ public:
+ ConvergencePayload();
+ virtual ~ConvergencePayload();
+ ConvergencePayload(const ConvergencePayload&) = delete;
+ ConvergencePayload(ConvergencePayload&&) = delete;
+ ConvergencePayload& operator=(const ConvergencePayload&) = delete;
+ ConvergencePayload& operator=(ConvergencePayload&&) = delete;
+
+ public:
+ void FromJson(const picojson::value &payload_json);
+
+ protected:
+ std::string id_;
+ ConvergencePayloadType type_;
+};
+
+class ConvergencePayloadString : public ConvergencePayload {
+ public:
+ ConvergencePayloadString();
+ virtual ~ConvergencePayloadString();
+ ConvergencePayloadString(const ConvergencePayloadString&) = delete;
+ ConvergencePayloadString(ConvergencePayloadString&&) = delete;
+ ConvergencePayloadString& operator=(const ConvergencePayloadString&) = delete;
+ ConvergencePayloadString& operator=(ConvergencePayloadString&&) = delete;
+
+ public:
+ void FromJson(const picojson::value &payload_json);
+
+ private:
+ std::string string_value_;
+};
+
+class ConvergencePayloadRawBytes : public ConvergencePayload {
+ public:
+ ConvergencePayloadRawBytes();
+ virtual ~ConvergencePayloadRawBytes();
+ ConvergencePayloadRawBytes(const ConvergencePayloadRawBytes&) = delete;
+ ConvergencePayloadRawBytes(ConvergencePayloadRawBytes&&) = delete;
+ ConvergencePayloadRawBytes& operator=(const ConvergencePayloadRawBytes&) = delete;
+ ConvergencePayloadRawBytes& operator=(ConvergencePayloadRawBytes&&) = delete;
+
+ public:
+ void FromJson(const picojson::value &payload_json);
+
+ private:
+ std::vector<unsigned char> raw_bytes_value_;
+};
+*/
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_PAYLOAD_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_remote_app_control_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_payload.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+namespace {
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; // ---
+static const std::string kServiceConnectionStatusConnected = "service_connected";
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected";
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+ConvergenceRemoteAppControlService::ConvergenceRemoteAppControlService()
+ : ConvergenceService()
+ , started_(false) {
+ ScopeLogger();
+}
+
+ConvergenceRemoteAppControlService::ConvergenceRemoteAppControlService(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceService(device, CONV_SERVICE_REMOTE_APP_CONTROL, convergence_plugin)
+ , started_(false) {
+ ScopeLogger();
+}
+
+ConvergenceRemoteAppControlService::~ConvergenceRemoteAppControlService() {
+ ScopeLogger();
+
+ // Release all memory, used by callback paramerers
+ for (size_t i = 0; i < callback_param_gc_.size(); i++) {
+ delete callback_param_gc_[i];
+ }
+ callback_param_gc_.clear();
+}
+
+void ConvergenceRemoteAppControlService::ServiceConnectedCb(conv_service_h service_handle,
+ conv_error_e error, conv_payload_h result, void* user_data) {
+ ScopeLogger();
+
+ CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+ if (!callbackParam) {
+ LoggerE("ERROR! NULL user data in Service Connect Callback");
+ return;
+ }
+
+ picojson::object param;
+ param["result_type"] = picojson::value("Connected");
+ //param[kPayload] = ConvergenceRemoteAppControlService::PayloadToJson(result);
+
+ if (CONV_ERROR_NONE == error) {
+ param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusConnected);
+ callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+ callbackParam->callback_id_,
+ true,
+ param);
+ } else {
+ // Error occured during connection
+ param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusNotConnected);
+ callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+ callbackParam->callback_id_,
+ false,
+ param);
+ }
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Connect(const int cur_listener_id) {
+ ScopeLogger();
+
+ conv_service_h service = FindServiceHandle();
+ if (!service) {
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ // TODO: make a garbage collection and release this memory when service is disconnected
+ // and when whole manager is destructed
+ CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+ callback_param_gc_.push_back(param);
+
+ const int error = conv_service_connect(service, ServiceConnectedCb, param);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_connect");
+ }
+
+ return TizenSuccess();
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Disconnect() {
+ ScopeLogger();
+
+ conv_service_h service = FindServiceHandle();
+ if (!service)
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+
+ const int error = conv_service_disconnect(service);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_disconnect");
+ }
+
+ return TizenSuccess();
+}
+
+void ConvergenceRemoteAppControlService::ServiceListenerCb(conv_service_h service_handle,
+ conv_channel_h channel_handle,
+ conv_error_e error, conv_payload_h result, void* user_data) {
+ ScopeLogger();
+
+ CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+ if (!callbackParam) {
+ LoggerE("ERROR! NULL user data in Service Listener Callback");
+ return;
+ }
+
+ picojson::object param;
+ param["payload"] = picojson::value("TODO");
+
+ // TODO parse the payload and fill the param
+
+ const std::string result_type = ConvergencePayloadArray::ExtractPayloadString(result, "result_type"); // TODO extract to constant kResultType = "result_type";
+ param["result_type"] = picojson::value(result_type);
+
+
+ if (CONV_ERROR_NONE == error) {
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+ callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+ callbackParam->callback_id_,
+ true,
+ param);
+ } else {
+ // Error occured during connection
+ param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusError);
+ param[kServiceListenerError] = picojson::value(static_cast<double>(error));
+ callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+ callbackParam->callback_id_,
+ false,
+ param);
+ }
+}
+
+void ConvergenceRemoteAppControlService::UpdateListener(const int cur_listener_id) {
+ ScopeLogger();
+ // TODO: make a garbage collection and release this memory when callback unset
+ // and when whole manager is destructed
+ CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+ callback_param_gc_.push_back(param);
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return;
+ }
+ const int error = conv_service_set_listener_cb(service_handle, ServiceListenerCb, param);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+ } else {
+ LoggerI("Listener is set correctly");
+ }
+}
+
+void ConvergenceRemoteAppControlService::EnsureStarted() {
+ ScopeLogger();
+ if (started_)
+ return;
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return; // TODO handle error
+ }
+
+ const int error = conv_service_start(service_handle, nullptr, nullptr);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_publish START");
+ } else {
+ LoggerI("APP CONTROL SERVICE IS STARTED");
+ started_ = true;
+ }
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Launch(const char *appId, bool reply, const int cur_listener_id) {
+ ScopeLogger();
+
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return LogAndCreateTizenError(NotFoundError,
+ "Service with specified type does not exist");
+ }
+
+ // Create app control payload with passed appId
+ conv_payload_h payload = CreateAppIdPayload(appId, reply);
+ if (!payload) {
+ // Handle error
+ return TizenSuccess(); // TODO TizenError
+ }
+
+ // Update listener: assign it if it is not yet assigned
+ if (reply)
+ UpdateListener(cur_listener_id);
+
+ // Ensure the service was started
+ EnsureStarted();
+
+ // Sending app control on the remote device
+ const int error = conv_service_publish(service_handle, nullptr, payload);
+ if (CONV_ERROR_NONE != error) {
+ // TODO: Handle error
+ trace_conv_error(error, __LINE__, "conv_service_publish LAUNCH");
+ } else {
+ LoggerI("---- SEEMS APP CONTROL WAS LAUNCHED ----");
+ }
+
+/*
+ conv_service_start(service_handle, NULL, NULL);
+ conv_payload_h payload_handle;
+ conv_payload_create(&payload_handle);
+ app_control_h app_control = NULL;
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, "org.example.d2d_test");
+ app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN);
+ conv_payload_set_app_control(payload_handle, "app_control", app_control);
+ conv_payload_set_string(payload_handle, "reply", "0");
+ conv_service_publish(service_handle, NULL, payload_handle);
+*/
+
+ conv_payload_destroy(payload);
+ return TizenSuccess();
+}
+
+conv_payload_h ConvergenceRemoteAppControlService::CreateAppIdPayload(const char *appId, bool reply) const {
+ ScopeLogger();
+
+ conv_payload_h payload = nullptr;
+ int error = conv_payload_create(&payload);
+ if (CONV_ERROR_NONE != error) {
+ // Handle error
+ }
+
+ app_control_h app_control = nullptr;
+ error = app_control_create(&app_control);
+ if (APP_CONTROL_ERROR_NONE != error) {
+ LoggerE("ERROR! AppControl API error [%d]", error);
+ }
+
+ error = app_control_set_app_id(app_control, appId);
+ if (APP_CONTROL_ERROR_NONE != error) {
+ LoggerE("ERROR! AppControl API error [%d]", error);
+ }
+
+ error = app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN);
+ if (CONV_ERROR_NONE != error) {
+ // Handle error
+ }
+
+ error = conv_payload_set_app_control(payload, "app_control", app_control);
+ if (APP_CONTROL_ERROR_NONE != error) {
+ // Handle error
+ }
+
+ if (reply) {
+ error = conv_payload_set_string(payload, "reply", "1");
+ if (CONV_ERROR_NONE != error) {
+ // Handle error
+ }
+ }
+
+ return payload;
+}
+
+picojson::value ConvergenceRemoteAppControlService::PayloadToJson(conv_payload_h payload) {
+ ScopeLogger();
+ picojson::value payload_json;
+
+ // TODO convert payload to array of ApplicationControlData
+
+ return payload_json;
+}
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceRemoteAppControlService : public ConvergenceService {
+
+ public:
+ ConvergenceRemoteAppControlService();
+ ConvergenceRemoteAppControlService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceRemoteAppControlService();
+ ConvergenceRemoteAppControlService(const ConvergenceRemoteAppControlService&) = delete;
+ ConvergenceRemoteAppControlService(ConvergenceRemoteAppControlService&&) = delete;
+ ConvergenceRemoteAppControlService& operator=(const ConvergenceRemoteAppControlService&) = delete;
+ ConvergenceRemoteAppControlService& operator=(ConvergenceRemoteAppControlService&&) = delete;
+ public:
+ common::TizenResult Connect(const int cur_listener_id);
+ common::TizenResult Disconnect();
+ common::TizenResult Launch(const char *appId, bool reply, const int cur_listener_id);
+ private:
+ conv_payload_h CreateAppIdPayload(const char *appId, bool reply) const;
+ static picojson::value PayloadToJson(conv_payload_h payload);
+ void UpdateListener(const int cur_listener_id);
+ void EnsureStarted();
+ static void ServiceConnectedCb(conv_service_h service_handle,
+ conv_error_e error, conv_payload_h result, void* user_data);
+ static void ServiceListenerCb(conv_service_h service_handle,
+ conv_channel_h channel_handle,
+ conv_error_e error, conv_payload_h result, void* user_data);
+
+ private:
+ std::vector<CallbackParam *> callback_param_gc_;
+ bool started_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kServiceType = "serviceType";
+static const std::string kServiceConnectionState = "connectionState";
+static const std::string kId = "id";
+static const std::string kVersion = "version";
+} // namespace
+
+ConvergenceService::ConvergenceService()
+ : convergence_plugin_(nullptr)
+ , device_(nullptr)
+ , type_(CONV_SERVICE_NONE)
+ , service_handle_(nullptr) {
+ ScopeLogger();
+}
+
+ConvergenceService::ConvergenceService(conv_device_h device, conv_service_e type, ConvergenceInstance *convergence_plugin)
+ : convergence_plugin_(convergence_plugin)
+ , device_(device)
+ , type_(type)
+ , service_handle_(nullptr) {
+ ScopeLogger();
+}
+
+ConvergenceService::~ConvergenceService() {
+ ScopeLogger();
+ LoggerI("DESTROYING SERVICE HANDLE [0x0%x] in ConvergenceService destr", service_handle_);
+ conv_service_destroy(service_handle_);
+}
+
+struct ServiceSearchQuery {
+ conv_service_h handle;
+ conv_service_e type;
+};
+
+void ConvergenceService::ForEachServiceCb(conv_service_h service_handle, void* user_data) {
+ ScopeLogger();
+ ServiceSearchQuery *query = static_cast<ServiceSearchQuery *>(user_data);
+ if (!query)
+ return;
+ if (query->handle)
+ return; // Already found a required service handle (no need to analyze something else)
+
+ conv_service_e type = CONV_SERVICE_NONE;
+ int error = conv_service_get_type(service_handle, &type);
+ if (error != CONV_ERROR_NONE) {
+ // TODO Handle error
+ }
+
+ if (type != query->type) {
+ return;
+ }
+ conv_service_h clone = nullptr;
+ error = conv_service_clone(service_handle, &clone);
+ if (error != CONV_ERROR_NONE) {
+ // TODO Handle error
+ }
+ query->handle = clone;
+}
+
+conv_service_h ConvergenceService::FindServiceHandle() const {
+ ScopeLogger();
+ if (!service_handle_) {
+
+ if (!device_) {
+ LoggerE("ERROR: Device handle is NULL, can not get device services");
+ return nullptr;
+ }
+
+ ServiceSearchQuery query = {nullptr, type_};
+ const int error = conv_device_foreach_service(device_, ForEachServiceCb, &query);
+ if (CONV_ERROR_NONE != error) {
+ // TODO Handle error
+ trace_conv_error(error, __LINE__, "conv_device_foreach_service");
+ }
+ service_handle_ = query.handle;
+ }
+ return service_handle_;
+}
+
+std::string ConvergenceService::ExtractServicePropery(conv_service_h service_handle,
+ const char *property) {
+ ScopeLogger();
+ char *value = nullptr;
+ const int error = conv_service_get_property_string(service_handle, property, &value);
+ if (CONV_ERROR_NONE != error) {
+ trace_conv_error(error, __LINE__, "conv_service_get_property_string");
+ return "";
+ }
+
+ if (value) {
+ const std::string result = std::string(value);
+ free(value);
+ return result;
+ }
+ return "";
+}
+
+void ConvergenceService::Refresh() {
+ ScopeLogger();
+ conv_service_h service_handle = FindServiceHandle();
+ if (!service_handle) {
+ LoggerE("AAAAAA!!! Service not found");
+ return;
+ }
+
+ conv_service_connection_state_e state = CONV_SERVICE_CONNECTION_STATE_NONE;
+ const int error = conv_service_get_connection_state(service_handle, &state);
+ if (CONV_ERROR_NONE != error) {
+ LoggerE("ERROR! D2D API Get Service Connection State error [%d]", error);
+ trace_conv_error(error, __LINE__, "conv_service_get_connection_state");
+ } else {
+ connection_state_ = state;
+ }
+
+ id_ = ExtractServicePropery(service_handle, CONV_SERVICE_ID);
+ version_ = ExtractServicePropery(service_handle, CONV_SERVICE_VERSION);
+
+ LoggerE("Refreshed service id [%s] version [%s] connection state [%d]",
+ id_.c_str(), version_.c_str(), connection_state_);
+
+ //conv_service_destroy(service_handle);
+ //LoggerI("DESTROYING SERVICE HANDLE [0x0%x] in ConvergenceService Refresh", service_handle_);
+}
+
+picojson::value ConvergenceService::ToJson() const {
+ ScopeLogger();
+ picojson::object service_json;
+
+ service_json[kServiceType] = picojson::value(static_cast<double>(type_));
+ service_json[kServiceConnectionState] = picojson::value(static_cast<double>(connection_state_));
+
+ // Following fields are not used in Web API layer now, but I parse it for
+ // future extensions
+ service_json[kId] = picojson::value(id_);
+ service_json[kVersion] = picojson::value(version_);
+
+ return picojson::value(service_json);
+}
+
+} // namespace convergence
+} // namespace extension
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceInstance;
+
+class ConvergenceService {
+
+ public:
+ ConvergenceService();
+ ConvergenceService(conv_device_h device, conv_service_e type, ConvergenceInstance *convergence_plugin);
+ virtual ~ConvergenceService();
+ ConvergenceService(const ConvergenceService&) = delete;
+ ConvergenceService(ConvergenceService&&) = delete;
+ ConvergenceService& operator=(const ConvergenceService&) = delete;
+ ConvergenceService& operator=(ConvergenceService&&) = delete;
+
+ public:
+ void Refresh();
+
+ public:
+ //conv_service_e get_type() const { return type_; }
+ //conv_device_h get_device() const {return device_; }
+ picojson::value ToJson() const;
+
+ protected:
+ conv_service_h FindServiceHandle() const;
+ static void ForEachServiceCb(conv_service_h service_handle, void* user_data);
+ std::string ExtractServicePropery(conv_service_h service_handle,
+ const char *property);
+
+ protected:
+ ConvergenceInstance *convergence_plugin_;
+
+ //private:
+ protected: // TODO switch back to private:
+ conv_device_h device_; // TODO rename to device_handle_
+ conv_service_e type_;
+ mutable conv_service_h service_handle_;
+ friend class ConvergenceAppCommunicationServerService; // It is needed to register the local service
+ private:
+ conv_service_connection_state_e connection_state_;
+ std::string id_;
+ std::string version_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_SERVICE_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO check includes
+#include "convergence/convergence_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+
+
+
+void trace_conv_error(const int error, int line_number, const char *extra_text) {
+ std::string error_text;
+ switch (error) {
+ case CONV_ERROR_NONE:
+ error_text = "CONV_ERROR_NONE";
+ break;
+ case CONV_ERROR_INVALID_PARAMETER:
+ error_text = "CONV_ERROR_INVALID_PARAMETER";
+ break;
+ case CONV_ERROR_INVALID_OPERATION:
+ error_text = "CONV_ERROR_INVALID_OPERATION";
+ break;
+ case CONV_ERROR_OUT_OF_MEMORY:
+ error_text = "CONV_ERROR_OUT_OF_MEMORY";
+ break;
+ case CONV_ERROR_PERMISSION_DENIED:
+ error_text = "CONV_ERROR_PERMISSION_DENIED";
+ break;
+ case CONV_ERROR_NOT_SUPPORTED:
+ error_text = "CONV_ERROR_NOT_SUPPORTED";
+ break;
+ case CONV_ERROR_NO_DATA:
+ error_text = "CONV_ERROR_NO_DATA";
+ break;
+ default:
+ error_text = "UNSUPPORTED D2D ERROR CODE";
+ break;
+ }
+
+ if (extra_text) {
+ LoggerE("ERROR! D2D API error [%s], line %d: %s", error_text.c_str(), line_number, extra_text);
+ } else {
+ LoggerE("ERROR! D2D API error [%s], line %d", error_text.c_str(), line_number);
+ }
+}
+
+
+
+} // namespace convergence
+} // namespace extension
* limitations under the License.
*/
-#ifndef SECUREELEMENT_CHANNEL_H_
-#define SECUREELEMENT_CHANNEL_H_
+#ifndef CONVERGENCE_CONVERGENCE_UTILS_H__
+#define CONVERGENCE_CONVERGENCE_UTILS_H__
-#include <ClientChannel.h>
-#include "common/picojson.h"
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
namespace extension {
-namespace secureelement {
-
-class SEChannel {
-public:
- SEChannel( smartcard_service_api::ClientChannel* channel_ptr) : m_channel_ptr(channel_ptr) {};
- virtual ~SEChannel() {};
- void close();
- smartcard_service_api::ByteArray transmit(const picojson::array& v_command);
- smartcard_service_api::ByteArray getSelectResponse();
-private:
- smartcard_service_api::ClientChannel* m_channel_ptr;
+namespace convergence {
+
+class ConvergenceInstance;
+
+struct CallbackParam {
+ CallbackParam(ConvergenceInstance *plg, int cbId)
+ : plugin_(plg), callback_id_(cbId) {}
+ ConvergenceInstance *plugin_;
+ int callback_id_;
};
-} // secureelement
-} // extension
-#endif // SECUREELEMENT_CHANNEL_H_
+void trace_conv_error(const int error, int line_number, const char *extra_text);
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_UTILS_H__
var types = validator.Types;
var T = xwalk.utils.type;
var kIdKey = Symbol();
+var converter = xwalk.converter;
function createListener(name, c) {
var listenerName = name;
ERROR: 'ERROR',
RESOURCE_CREATED: 'RESOURCE_CREATED',
RESOURCE_DELETED: 'RESOURCE_DELETED',
+ RESOURCE_CHANGED: 'RESOURCE_CHANGED',
SLOW: 'SLOW',
FORBIDDEN: 'FORBIDDEN',
};
HIGH: 'HIGH'
};
+var RequestType = {
+ UNKNOWN: 'UNKNOWN',
+ GET: 'GET',
+ PUT: 'PUT',
+ POST: 'POST',
+ DELETE: 'DELETE'
+};
+
+var ObserveType = {
+ NO_TYPE: 'NO_TYPE',
+ REGISTER: 'REGISTER',
+ DEREGISTER: 'DEREGISTER'
+};
+
function DeviceInfo(data) {
decorateWithData(data, this);
}
writable: true,
enumerable: true
},
- states: {
+ attributes: {
value: null,
writable: true,
enumerable: true
},
- representations: {
+ children: {
value: null,
writable: true,
enumerable: true
function createRepresentation(data) {
var r = new tizen.Representation(data.uriPath);
- var props = ['resourceTypes', 'resourceInterfaces', 'states'];
+ var props = ['resourceTypes', 'resourceInterfaces', 'attributes'];
for (var p = 0; p < props.length; ++p) {
if (data[props[p]]) {
}
}
- if (data.representations) {
- r.representations = [];
- for (var i = 0; i < data.representations.length; ++i) {
- r.representations.push(createRepresentation(data.representations[i]));
+ if (data.children) {
+ r.children = [];
+ for (var i = 0; i < data.children.length; ++i) {
+ r.children.push(createRepresentation(data.children[i]));
}
}
var internal = new InternalData(data);
internal.decorate(this);
- this.states = null;
+ this.attributes = null;
}
Resource.prototype.notify = function() {
nullable: true
}]);
- var states = {};
- function getStates(r) {
- states[r[kIdKey]] = r.states;
+ var attributes = {};
+ function getAttributes(r) {
+ attributes[r[kIdKey]] = r.attributes;
for (var i = 0; i < r.resources.length; ++i) {
- getStates(r.resources[i]);
+ getAttributes(r.resources[i]);
}
}
- getStates(this);
+ getAttributes(this);
var callArgs = {};
callArgs.id = this[kIdKey];
callArgs.qos = args.qos;
callArgs.observerIds = args.observerIds;
- callArgs.states = states;
+ callArgs.attributes = attributes;
var result = native.callSync('IotconResource_notify', callArgs);
}
};
-var resourceRequestListener = createListener('ResourceRequestListener', function(response) {
- return new Request(response.data);
-});
-
-Resource.prototype.setRequestListener = function() {
- var args = validator.validateMethod(arguments, [{
- name: 'successCallback',
- type: types.FUNCTION
- }]);
+var resourceRequestListener = createListener('ResourceRequestListener');
+var _setRequestListener = function(id, listener) {
var callArgs = {};
- callArgs.id = this[kIdKey];
+ callArgs.id = id;
var listener = function(result) {
- args.successCallback(result);
+ var request = new Request(result.data.request);
+ switch (converter.toString(result.data.type, false)) {
+ case RequestType.GET:
+ native.callIfPossible(listener.onget, request);
+ break;
+
+ case RequestType.PUT:
+ native.callIfPossible(listener.onput, request);
+ break;
+
+ case RequestType.POST:
+ native.callIfPossible(listener.onpost, request);
+ break;
+
+ case RequestType.DELETE:
+ native.callIfPossible(listener.ondelete, request);
+ break;
+ }
+
+ var observeType = converter.toString(result.data.observeType, false);
+ var observerId = converter.toUnsignedLong(result.data.observerId, false);
+ if (observeType !== ObserveType.NO_TYPE && observerId) {
+ native.callIfPossible(listener.onobserving(request, observeType, observerId));
+ }
};
var result = native.callSync('IotconResource_setRequestListener', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
- resourceRequestListener.addListener(this[kIdKey], listener);
+ resourceRequestListener.addListener(id, listener);
}
};
+Resource.prototype.setRequestListener = function() {
+ var args = validator.validateMethod(arguments, [{
+ name: 'listener',
+ type: types.LISTENER,
+ values: ['onget', 'onput', 'onpost', 'ondelete', 'onobserving']
+ }]);
+
+ _setRequestListener(this[kIdKey], args.listener);
+};
+
Resource.prototype.unsetRequestListener = function() {
var callArgs = {};
callArgs.id = this[kIdKey];
}
};
-
function Response(request) {
validator.isConstructorCall(this, tizen.Response);
}
Response.prototype.send = function() {
- var args = validator.validateMethod(arguments, [{
- name: 'iface',
- type: types.STRING
- }]);
-
var callArgs = {};
callArgs.id = this.request[kIdKey];
callArgs.result = this.result;
callArgs.representation = this.representation;
callArgs.options = this.options;
- callArgs.iface = args.iface;
var result = native.callSync('IotconResponse_send', callArgs);
});
}
-function prepareResourceInfo(that){
+function prepareResourceInfo(that, notIncludeOptions){
var callArgs = {};
callArgs.id = that[kIdKey];
if (!callArgs.id) {
callArgs.isExplicitDiscoverable = that.isExplicitDiscoverable;
callArgs.resourceTypes = that.resourceTypes;
callArgs.resourceInterfaces = that.resourceInterfaces;
+ if (!notIncludeOptions) {
+ callArgs.options = that.options;
+ }
} else {
console.log("Already stored in C++, all needed info is id");
}
Object.defineProperties(this, {
cachedRepresentation: {
get: function() {
- var callArgs = {};
- callArgs.id = this[kIdKey];
+ var callArgs = prepareResourceInfo(this);
var result = native.callSync('IotconRemoteResource_getCachedRepresentation', callArgs);
if (native.isSuccess(result)) {
return createRepresentation(native.getResultObject(result));
enumerable: true
},
options: {
- value: null,
- writable: true,
+ get: function() {
+ var options_ = null;
+ var callArgs = prepareResourceInfo(this, true);
+ var result = native.callSync('IotconRemoteResource_getOptions', callArgs);
+ if (native.isSuccess(result)) {
+ var data = native.getResultObject(result);
+ options_ = [];
+ for (var i = 0; i < data.length; ++i) {
+ options_.push(new IotconOption(data[i].id, data[i].data));
+ }
+ }
+ return options_;
+ }.bind(this),
+ set: function(val) {
+ // array or null are only acceptable values
+ if (!T.isArray(val) && null != val) {
+ return;
+ }
+ // check types of array values
+ if (T.isArray(val)) {
+ for (var i = 0; i < val.length; ++i) {
+ if (!(val[i] instanceof tizen.IotconOption)) {
+ return;
+ }
+ }
+ }
+
+ var callArgs = prepareResourceInfo(this, true);
+ callArgs['options'] = val;
+
+ var result = native.callSync('IotconRemoteResource_setOptions', callArgs);
+ if (native.isSuccess(result)) {
+ manageId(this, native.getResultObject(result));
+ }
+ }.bind(this),
+ enumerable: true
+ },
+ timeInterval: {
+ get: function() {
+ /* TODO Uncomment when the interface of the function iotcon_remote_resource_get_time_interval is changed
+ var callArgs = prepareResourceInfo(this, true);
+ */
+ var callArgs = {};
+
+ var result = native.callSync('IotconRemoteResource_getTimeInterval', callArgs);
+ if (native.isSuccess(result)) {
+ return native.getResultObject(result);
+ }
+ return null;
+ }.bind(this),
+ set: function(val) {
+ /* TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+ var callArgs = prepareResourceInfo(this, true);
+ callArgs[timeInterval] = converter.toLong(val);
+ */
+ var callArgs = {
+ timeInterval: converter.toLong(val)
+ };
+
+ native.callSync('IotconRemoteResource_setTimeInterval', callArgs);
+ }.bind(this),
enumerable: true
}
});
RemoteResource.prototype.methodGet = function() {
var args = validator.validateMethod(arguments, [{
- name: 'query',
- type: types.DICTIONARY
- }, {
name: 'responseCallback',
type: types.FUNCTION
}, {
+ name: 'query',
+ type: types.DICTIONARY,
+ optional: true,
+ nullable: true
+ }, {
name: 'errorCallback',
type: types.FUNCTION,
optional: true,
}]);
var callArgs = prepareResourceInfo(this);
- callArgs.query = args.query;
+ if (args.query) {
+ callArgs.query = args.query;
+ }
var callback = function(result) {
result = native.getResultObject(result);
type: types.PLATFORM_OBJECT,
values: Representation
}, {
- name: 'query',
- type: types.DICTIONARY
- }, {
name: 'responseCallback',
type: types.FUNCTION
}, {
+ name: 'query',
+ type: types.DICTIONARY,
+ optional: true,
+ nullable: true
+ }, {
name: 'errorCallback',
type: types.FUNCTION,
optional: true,
var callArgs = prepareResourceInfo(this);
callArgs.representation = args.representation;
- callArgs.query = args.query;
+ if (args.query) {
+ callArgs.query = args.query;
+ }
var callback = function(result) {
result = native.getResultObject(result);
type: types.PLATFORM_OBJECT,
values: Representation
}, {
- name: 'query',
- type: types.DICTIONARY
- }, {
name: 'responseCallback',
type: types.FUNCTION
}, {
+ name: 'query',
+ type: types.DICTIONARY,
+ optional: true,
+ nullable: true
+ }, {
name: 'errorCallback',
type: types.FUNCTION,
optional: true,
var callArgs = prepareResourceInfo(this);
callArgs.representation = args.representation;
- callArgs.query = args.query;
+ if (args.query) {
+ callArgs.query = args.query;
+ }
var callback = function(result) {
result = native.getResultObject(result);
}
};
-var stateChangeListener = createListener('RemoteResourceStateChangeListener');
+var resourceChangeListener = createListener('RemoteResourceChangeListener');
-RemoteResource.prototype.setStateChangeListener = function() {
+RemoteResource.prototype.startObserving = function() {
var args = validator.validateMethod(arguments, [{
- name: 'query',
- type: types.DICTIONARY
- }, {
name: 'observePolicy',
type: types.ENUM,
values: T.getValues(ObservePolicy)
}, {
name: 'successCallback',
type: types.FUNCTION
+ }, {
+ name: 'query',
+ type: types.DICTIONARY,
+ optional: true,
+ nullable: true
}]);
var callArgs = prepareResourceInfo(this);
- callArgs.query = args.query;
callArgs.observePolicy = args.observePolicy;
+ if (args.query) {
+ callArgs.query = args.query;
+ }
var that = this;
var listener = function(result) {
args.successCallback(new RemoteResponse(result.data));
};
- var result = native.callSync('IotconRemoteResource_setStateChangeListener', callArgs);
+ var result = native.callSync('IotconRemoteResource_startObserving', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
- stateChangeListener.addListener(this[kIdKey], listener);
+ resourceChangeListener.addListener(this[kIdKey], listener);
}
};
-RemoteResource.prototype.unsetStateChangeListener = function() {
+RemoteResource.prototype.stopObserving = function() {
var callArgs = prepareResourceInfo(this);
- var result = native.callSync('IotconRemoteResource_unsetStateChangeListener', callArgs);
+ var result = native.callSync('IotconRemoteResource_stopObserving', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
- stateChangeListener.removeListener(this[kIdKey]);
+ resourceChangeListener.removeListener(this[kIdKey]);
}
};
+var cacheChangeListener = createListener('RemoteResourceCacheChangeListener');
+
RemoteResource.prototype.startCaching = function() {
+ var args = validator.validateMethod(arguments, [{
+ name: 'successCallback',
+ type: types.FUNCTION,
+ optional: true,
+ nullable: true
+ }]);
+
var callArgs = prepareResourceInfo(this);
+ var listener = function(result) {
+ native.callIfPossible(args.successCallback(createRepresentation(native.getResultObject(result.data))));
+ }
+
var result = native.callSync('IotconRemoteResource_startCaching', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
+ cacheChangeListener.addListener(this[kIdKey], listener);
}
};
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
+ cacheChangeListener.removeListener(this[kIdKey]);
}
};
-var connectionChangeListener = createListener('RemoteResourceConnectionChangeListener');
+var resourceStateChangeListener = createListener('RemoteResourceStateChangeListener');
-RemoteResource.prototype.setConnectionChangeListener = function() {
+RemoteResource.prototype.setResourceStateChangeListener = function() {
var args = validator.validateMethod(arguments, [{
name: 'successCallback',
type: types.FUNCTION
args.successCallback(result.data);
};
- var result = native.callSync('IotconRemoteResource_setConnectionChangeListener', callArgs);
+ var result = native.callSync('IotconRemoteResource_setResourceStateChangeListener', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
- connectionChangeListener.addListener(this[kIdKey], listener);
+ resourceStateChangeListener.addListener(this[kIdKey], listener);
}
};
-RemoteResource.prototype.unsetConnectionChangeListener = function() {
+RemoteResource.prototype.unsetResourceStateChangeListener = function() {
var callArgs = prepareResourceInfo(this);
- var result = native.callSync('IotconRemoteResource_unsetConnectionChangeListener', callArgs);
+ var result = native.callSync('IotconRemoteResource_unsetResourceStateChangeListener', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
} else {
manageId(this, native.getResultObject(result));
- connectionChangeListener.removeListener(this[kIdKey]);
+ resourceStateChangeListener.removeListener(this[kIdKey]);
}
};
type: types.STRING,
nullable: true
}, {
- name: 'resourceType',
- type: types.STRING,
+ name: 'query',
+ type: types.DICTIONARY,
nullable: true
}, {
name: 'connectivityType',
type: types.FUNCTION,
optional: true,
nullable: true
- }, {
- name: 'isSecure',
- type: types.BOOLEAN
}]);
var callArgs = {};
callArgs.id = ++globalFindResourceId;
callArgs.hostAddress = args.hostAddress;
- callArgs.resourceType = args.resourceType;
+ callArgs.query = args.query;
callArgs.connectivityType = args.connectivityType;
- callArgs.isSecure = args.isSecure;
var callback = function(result) {
if (native.isFailure(result)) {
}
};
-Client.prototype.getDeviceInfo = function() {
+Client.prototype.findDeviceInfo = function() {
var args = validator.validateMethod(arguments, [{
name: 'hostAddress',
- type: types.STRING
+ type: types.STRING,
+ nullable: true
+ }, {
+ name: 'query',
+ type: types.DICTIONARY,
+ nullable: true
}, {
name: 'connectivityType',
type: types.ENUM,
}]);
var callArgs = {};
+
callArgs.hostAddress = args.hostAddress;
+ callArgs.query = args.query;
callArgs.connectivityType = args.connectivityType;
var callback = function(result) {
}
};
- var result = native.call('IotconClient_getDeviceInfo', callArgs, callback);
+ var result = native.call('IotconClient_findDeviceInfo', callArgs, callback);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
}
};
-Client.prototype.getPlatformInfo = function() {
+Client.prototype.findPlatformInfo = function() {
var args = validator.validateMethod(arguments, [{
name: 'hostAddress',
- type: types.STRING
+ type: types.STRING,
+ nullable: true
+ }, {
+ name: 'query',
+ type: types.DICTIONARY,
+ nullable: true
}, {
name: 'connectivityType',
type: types.ENUM,
var callArgs = {};
callArgs.hostAddress = args.hostAddress;
+ callArgs.query = args.query;
callArgs.connectivityType = args.connectivityType;
var callback = function(result) {
}
};
- var result = native.call('IotconClient_getPlatformInfo', callArgs, callback);
+ var result = native.call('IotconClient_findPlatformInfo', callArgs, callback);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
};
function Server() {
+ // TODO The variable _deviceName will be removed when the native function for getting device name is ready
+ var _deviceName = '';
+
+ Object.defineProperties(this, {
+ deviceName: {
+ get: function() {
+ return _deviceName;
+ },
+ set: function(v) {
+ if (v) {
+ var deviceName = converter.toString(v);
+
+ var callArgs = {
+ deviceName: deviceName
+ };
+
+ var result = native.callSync('IotconServer_setDeviceName', callArgs);
+ if (native.isSuccess(result)) {
+ _deviceName = deviceName;
+ }
+ }
+ },
+ enumerable: true
+ }
+ });
}
var serverResources = {};
type: types.ARRAY,
values: types.STRING
}, {
- name: 'dictionary',
+ name: 'listener',
+ type: types.LISTENER,
+ values: ['onget', 'onput', 'onpost', 'ondelete', 'onobserving']
+ }, {
+ name: 'policy',
type: types.DICTIONARY,
optional: true,
nullable: false
}]);
- var callArgs = args.dictionary || {};
+ var callArgs = args.policy || {};
callArgs.uriPath = args.uriPath;
callArgs.resourceTypes = args.resourceTypes;
callArgs.resourceInterfaces = args.resourceInterfaces;
} else {
var resource = new Resource(native.getResultObject(result));
serverResources[resource[kIdKey]] = resource;
+
+ _setRequestListener(resource[kIdKey], args.listener);
+
return resource;
}
};
return result;
};
+Server.prototype.startPresence = function() {
+ var args = validator.validateMethod(arguments, [{
+ name: 'timeToLive',
+ type: types.UNSIGNED_LONG
+ }]);
+
+ var callArgs = {
+ timeToLive: args.timeToLive
+ };
+
+ var result = native.callSync('IotconServer_startPresence', callArgs);
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+};
+
+Server.prototype.stopPresence = function() {
+ var result = native.callSync('IotconServer_stopPresence', {});
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+};
+
var client = new Client();
var server = new Server();
function Iotcon() {
}
+Iotcon.prototype.initialize = function() {
+ var args = validator.validateMethod(arguments, [{
+ name: 'filePath',
+ type: types.STRING
+ }]);
+
+ var data = {
+ filePath: args.filePath
+ };
+
+ var result = native.callSync('Iotcon_initialize', data);
+
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+};
+
Iotcon.prototype.getClient = function() {
return client;
};
namespace iotcon {
namespace {
-const std::string kPrivilegeIotcon = "http://tizen.org/privilege/d2d.datasharing";
+const std::string kPrivilegeIotcon = "http://tizen.org/privilege/internet";
struct CallbackData {
common::PostCallback fun;
const common::ListenerToken kResourceRequestListenerToken{"ResourceRequestListener"};
const common::ListenerToken kFindResourceListenerToken{"FindResourceListener"};
const common::ListenerToken kPresenceEventListenerToken{"PresenceEventListener"};
-const common::ListenerToken kRemoteResourceConnectionChangeListener
- {"RemoteResourceConnectionChangeListener"};
const common::ListenerToken kRemoteResourceStateChangeListener
{"RemoteResourceStateChangeListener"};
+const common::ListenerToken kRemoteResourceChangeListener
+ {"RemoteResourceChangeListener"};
+const common::ListenerToken kRemoteResourceCacheChangeListener
+ {"RemoteResourceCacheChangeListener"};
const std::string kObserverIds = "observerIds";
const std::string kQos = "qos";
const std::string kResult = "result";
const std::string kTimeout = "timeout";
const std::string kData = "data";
+const std::string kFilePath = "filePath";
+const std::string kTimeToLive = "timeToLive";
+
+const std::string kTimeInterval = "timeInterval";
const std::string kVirtualResourcesHandlingPath = "/home/owner/share/tmp_file_iotcon.dat";
} // namespace
-IotconInstance::IotconInstance() {
+IotconInstance::IotconInstance() : initialized_(false), presence_started_(false) {
ScopeLogger();
using std::placeholders::_1;
REGISTER_SYNC("IotconResource_unsetRequestListener", ResourceUnsetRequestListener);
REGISTER_SYNC("IotconResponse_send", ResponseSend);
REGISTER_SYNC("IotconRemoteResource_getCachedRepresentation", RemoteResourceGetCachedRepresentation);
- REGISTER_SYNC("IotconRemoteResource_setStateChangeListener", RemoteResourceSetStateChangeListener);
- REGISTER_SYNC("IotconRemoteResource_unsetStateChangeListener", RemoteResourceUnsetStateChangeListener);
+ REGISTER_SYNC("IotconRemoteResource_getOptions", RemoteResourceGetOptions);
+ REGISTER_SYNC("IotconRemoteResource_setOptions", RemoteResourceSetOptions);
+ REGISTER_SYNC("IotconRemoteResource_startObserving", RemoteResourceStartObserving);
+ REGISTER_SYNC("IotconRemoteResource_stopObserving", RemoteResourceStopObserving);
REGISTER_SYNC("IotconRemoteResource_startCaching", RemoteResourceStartCaching);
REGISTER_SYNC("IotconRemoteResource_stopCaching", RemoteResourceStopCaching);
- REGISTER_SYNC("IotconRemoteResource_setConnectionChangeListener", RemoteResourceSetConnectionChangeListener);
- REGISTER_SYNC("IotconRemoteResource_unsetConnectionChangeListener", RemoteResourceUnsetConnectionChangeListener);
+ REGISTER_SYNC("IotconRemoteResource_setResourceStateChangeListener", RemoteResourceSetResourceStateChangeListener);
+ REGISTER_SYNC("IotconRemoteResource_unsetResourceStateChangeListener", RemoteResourceUnsetResourceStateChangeListener);
+ REGISTER_SYNC("IotconRemoteResource_getTimeInterval", RemoteResourceGetTimeInterval);
+ REGISTER_SYNC("IotconRemoteResource_setTimeInterval", RemoteResourceSetTimeInterval);
REGISTER_SYNC("IotconClient_addPresenceEventListener", ClientAddPresenceEventListener);
REGISTER_SYNC("IotconClient_removePresenceEventListener", ClientRemovePresenceEventListener);
+ REGISTER_SYNC("Iotcon_initialize", Initialize);
REGISTER_SYNC("Iotcon_getTimeout", GetTimeout);
REGISTER_SYNC("Iotcon_setTimeout", SetTimeout);
REGISTER_SYNC("IotconServer_createResource", ServerCreateResource);
REGISTER_SYNC("IotconServer_removeResource", ServerRemoveResource);
+ REGISTER_SYNC("IotconServer_startPresence", ServerStartPresence);
+ REGISTER_SYNC("IotconServer_stopPresence", ServerStopPresence);
+ REGISTER_SYNC("IotconServer_setDeviceName", ServerSetDeviceName);
REGISTER_SYNC("IotconClient_findResource", ClientFindResource);
#undef REGISTER_SYNC
REGISTER_ASYNC("IotconRemoteResource_methodPut", RemoteResourceMethodPut);
REGISTER_ASYNC("IotconRemoteResource_methodPost", RemoteResourceMethodPost);
REGISTER_ASYNC("IotconRemoteResource_methodDelete", RemoteResourceMethodDelete);
- REGISTER_ASYNC("IotconClient_getDeviceInfo", ClientGetDeviceInfo);
- REGISTER_ASYNC("IotconClient_getPlatformInfo", ClientGetPlatformInfo);
+ REGISTER_ASYNC("IotconClient_findDeviceInfo", ClientFindDeviceInfo);
+ REGISTER_ASYNC("IotconClient_findPlatformInfo", ClientFindPlatformInfo);
#undef REGISTER_ASYNC
-
- // initialize connection to iotcon service
- int ret = iotcon_initialize(kVirtualResourcesHandlingPath.c_str());
- if (IOTCON_ERROR_NONE != ret) {
- LoggerE("Could not connnect to iotcon service: %s", get_error_message(ret));
- } else {
- LoggerD("Iotcon service connected");
-
- ret = iotcon_start_presence(0);
- if (IOTCON_ERROR_NONE != ret) {
- LoggerE("Could not start presence: %s",
- get_error_message(ret));
- } else {
- LoggerD("Iotcon iotcon_start_presence");
- }
- }
}
IotconInstance::~IotconInstance() {
ScopeLogger();
- iotcon_stop_presence();
- iotcon_deinitialize();
+ if (presence_started_) {
+ iotcon_stop_presence();
+ presence_started_ = false;
+ LoggerD("Iotcon service presence stopped");
+ }
+
+ if (initialized_) {
+ iotcon_deinitialize();
+ initialized_ = false;
+ LoggerD("Iotcon service deinitialized");
+ }
}
common::TizenResult IotconInstance::ResourceGetObserverIds(const picojson::object& args) {
CHECK_EXIST(args, kId);
CHECK_EXIST(args, kQos);
- CHECK_EXIST(args, kStates);
+ CHECK_EXIST(args, kAttributes);
ResourceInfoPtr resource;
long long id = GetId(args);
}
}
- // create representation from resource and states
+ // create representation from resource and attributes
iotcon_representation_h representation = nullptr;
- result = IotconUtils::RepresentationFromResource(resource, IotconUtils::GetArg(args, kStates), &representation);
+ result = IotconUtils::RepresentationFromResource(resource, IotconUtils::GetArg(args, kAttributes), &representation);
if (!result) {
LogAndReturnTizenError(result, ("RepresentationFromResource() failed"));
}
const auto& types = IotconUtils::GetArg(args, kTypes).get<picojson::array>();
for (const auto& type : types) {
- result = IotconUtils::ConvertIotconError(iotcon_resource_bind_type(resource->handle, type.get<std::string>().c_str()));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_resource_bind_type() failed"));
+ int ret = iotcon_resource_bind_type(resource->handle, type.get<std::string>().c_str());
+ if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+ LogAndReturnTizenError(
+ IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_type() failed"));
}
}
LogAndReturnTizenError(result, ("GetResourceById() failed"));
}
- result = IotconUtils::ConvertIotconError(iotcon_resource_bind_interface(resource->handle, IotconUtils::GetArg(args, kInterface).get<std::string>().c_str()));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_resource_bind_interface() failed"));
+ int ret = iotcon_resource_bind_interface(
+ resource->handle, IotconUtils::GetArg(args, kInterface).get<std::string>().c_str());
+ if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+ LogAndReturnTizenError(
+ IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_interface() failed"));
}
return common::TizenSuccess();
LogAndReturnTizenError(result, ("GetResourceById() failed"));
}
- result = IotconUtils::ConvertIotconError(iotcon_resource_bind_child_resource(parent->handle, child->handle));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_resource_bind_child_resource() failed"));
+ int ret = iotcon_resource_bind_child_resource(parent->handle, child->handle);
+ if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+ LogAndReturnTizenError(
+ IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_child_resource() failed"));
}
parent->children.insert(child);
}
if (!resource->request_listener) {
- resource->request_listener = [this, id](const common::TizenResult&, const picojson::value& v) {
+ resource->request_listener = [this, id](const common::TizenResult&,
+ const picojson::value& v) {
picojson::value response{picojson::object{}};
auto& obj = response.get<picojson::object>();
CHECK_EXIST(args, kResult);
CHECK_EXIST(args, kRepresentation);
CHECK_EXIST(args, kOptions);
- CHECK_EXIST(args, kInterface);
ResponsePtr response = nullptr;
auto result = IotconServerManager::GetInstance().GetResponseById(GetId(args), &response);
}
return common::TizenSuccess{repr_json};
}
- return common::UnknownError("Failed to gather cached representation");
+ return common::AbortError("Failed to gather cached representation");
+}
+
+common::TizenResult IotconInstance::RemoteResourceGetOptions(const picojson::object& args) {
+ ScopeLogger();
+
+ FoundRemoteInfoPtr ptr;
+ auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+ if (!res) {
+ LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+ }
+
+ iotcon_options_h options = nullptr;
+ res = IotconUtils::ConvertIotconError(
+ iotcon_remote_resource_get_options(ptr->handle, &options));
+ if (!res) {
+ LogAndReturnTizenError(res, ("Gathering options failed"));
+ }
+
+ if (options) {
+ picojson::array options_array;
+ res = IotconUtils::OptionsToJson(options, &options_array);
+ if (!res) {
+ LogAndReturnTizenError(res, ("OptionsToJson() failed"));
+ }
+ return common::TizenSuccess{picojson::value(options_array)};
+ }
+
+ return common::AbortError("Failed to gather options");
+}
+
+common::TizenResult IotconInstance::RemoteResourceSetOptions(const picojson::object& args) {
+ ScopeLogger();
+ CHECK_EXIST(args, kOptions);
+
+ FoundRemoteInfoPtr ptr;
+ auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+ if (!res) {
+ LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+ }
+
+ // default value would be null (if provided value is not an array)
+ iotcon_options_h options = nullptr;
+ const auto& options_it = args.find(kOptions);
+ if (options_it->second.is<picojson::array>()) {
+ // if it is an array use provided values
+ const auto& options_array = options_it->second.get<picojson::array>();
+ res = IotconUtils::OptionsFromJson(options_array, &options);
+ if (!res) {
+ return res;
+ }
+ }
+
+ res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_options(ptr->handle, options));
+ if (!res) {
+ LogAndReturnTizenError(res, ("iotcon_response_set_options() failed"));
+ }
+
+ return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
}
common::TizenResult IotconInstance::RemoteResourceMethodGet(const picojson::object& args,
CHECK_PRIVILEGE(kPrivilegeIotcon);
- CHECK_EXIST(args, kQuery);
-
FoundRemoteInfoPtr resource;
auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
if (!result) {
}
iotcon_query_h query = nullptr;
- result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
- if (!result) {
- LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ const auto& query_it = args.find(kQuery);
+ if (args.end() != query_it) {
+ result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
}
SCOPE_EXIT {
- iotcon_query_destroy(query);
+ if (query) {
+ iotcon_query_destroy(query);
+ }
};
std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
CHECK_PRIVILEGE(kPrivilegeIotcon);
CHECK_EXIST(args, kRepresentation);
- CHECK_EXIST(args, kQuery);
FoundRemoteInfoPtr resource;
auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
};
iotcon_query_h query = nullptr;
- result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
- if (!result) {
- LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ const auto& query_it = args.find(kQuery);
+ if (args.end() != query_it) {
+ result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
}
SCOPE_EXIT {
- iotcon_query_destroy(query);
+ if (query) {
+ iotcon_query_destroy(query);
+ }
};
std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
CHECK_PRIVILEGE(kPrivilegeIotcon);
CHECK_EXIST(args, kRepresentation);
- CHECK_EXIST(args, kQuery);
FoundRemoteInfoPtr resource;
auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
};
iotcon_query_h query = nullptr;
- result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
- if (!result) {
- LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ const auto& query_it = args.find(kQuery);
+ if (args.end() != query_it) {
+ result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
}
SCOPE_EXIT {
- iotcon_query_destroy(query);
+ if (query) {
+ iotcon_query_destroy(query);
+ }
};
std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
int sequence_number, iotcon_response_h response, void *user_data) {
ScopeLogger();
FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
+ if (nullptr == ptr) {
+ LoggerE("ObserveCallback() failed. Ignoring callback");
+ return;
+ }
+
if (ptr->observe_listener) {
picojson::value json_result = picojson::value(picojson::object());
}
}
-common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceStartObserving(const picojson::object& args) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
- CHECK_EXIST(args, kQuery);
CHECK_EXIST(args, kObservePolicy);
FoundRemoteInfoPtr ptr;
auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
}
iotcon_query_h query = nullptr;
- auto query_obj = args.find(kQuery)->second.get<picojson::object>();
- result = IotconUtils::QueryFromJson(query_obj, &query);
- if (!result){
- return result;
+ const auto& query_it = args.find(kQuery);
+ if (args.end() != query_it) {
+ result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+ if (!result){
+ return result;
+ }
}
SCOPE_EXIT {
- iotcon_query_destroy(query);
+ if (query) {
+ iotcon_query_destroy(query);
+ }
};
iotcon_observe_policy_e observe_policy = IotconUtils::ToObservePolicy(
obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
obj.insert(std::make_pair(kData, v));
- Post(kRemoteResourceStateChangeListener, common::TizenSuccess{response});
+ Post(kRemoteResourceChangeListener, common::TizenSuccess{response});
};
// set options to the remote resource
return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
}
-common::TizenResult IotconInstance::RemoteResourceUnsetStateChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceStopObserving(const picojson::object& args) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
static void RepresentationChangedCallback(iotcon_remote_resource_h resource,
iotcon_representation_h representation,
void *user_data) {
- LoggerD("Entered");
- //TODO probably should be handled
+ ScopeLogger();
+ FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
+ if (nullptr == ptr) {
+ LoggerE("RepresentationChangeCallback() failed. Ignoring callback");
+ return;
+ }
+
+ if (ptr->cache_change_listener) {
+ picojson::value json_result = picojson::value(picojson::object());
+
+ auto result = IotconUtils::RepresentationToJson(representation, &json_result.get<picojson::object>());
+ if (result) {
+ ptr->cache_change_listener(common::TizenSuccess(), json_result);
+ } else {
+ LoggerE("RepresentationToJson() failed. Ignoring callback");
+ return;
+ }
+ }
}
common::TizenResult IotconInstance::RemoteResourceStartCaching(const picojson::object& args) {
if (!result) {
LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
}
+
+ ptr->cache_change_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
+ picojson::value response{picojson::object{}};
+ auto& obj = response.get<picojson::object>();
+
+ obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
+ obj.insert(std::make_pair(kData, v));
+
+ Post(kRemoteResourceCacheChangeListener, common::TizenSuccess{response});
+ };
+
result = IotconUtils::ConvertIotconError(
- iotcon_remote_resource_start_caching(ptr->handle, RepresentationChangedCallback, nullptr));
+ iotcon_remote_resource_start_caching(ptr->handle, RepresentationChangedCallback, ptr.get()));
if (!result) {
return result;
}
+
return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
}
if (!result) {
LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
}
+
result = IotconUtils::ConvertIotconError(
iotcon_remote_resource_stop_caching(ptr->handle));
if (!result) {
return result;
}
+ ptr->cache_change_listener = nullptr;
return common::TizenSuccess{IotconClientManager::GetInstance().RemoveRemoteResource(ptr)};
}
iotcon_remote_resource_state_e state, void *user_data) {
ScopeLogger();
FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
- if (ptr->connection_listener) {
+ if (nullptr == ptr) {
+ LoggerE("MonitoringCallback() failed. Ignoring callback");
+ return;
+ }
+
+ if (ptr->state_listener) {
picojson::value json_result = picojson::value(IOTCON_REMOTE_RESOURCE_ALIVE == state);
- ptr->connection_listener(common::TizenSuccess(), json_result);
+ ptr->state_listener(common::TizenSuccess(), json_result);
} else {
LoggerD("Post function not present, just ignoring");
}
}
-common::TizenResult IotconInstance::RemoteResourceSetConnectionChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceSetResourceStateChangeListener(const picojson::object& args) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
+
FoundRemoteInfoPtr ptr;
auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
if (!result) {
LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
}
- result = IotconUtils::ConvertIotconError(
- iotcon_remote_resource_start_monitoring(ptr->handle, MonitoringCallback, ptr.get()));
- if (!result) {
- return result;
- }
- ptr->connection_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
+
+ ptr->state_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
picojson::value response{picojson::object{}};
auto& obj = response.get<picojson::object>();
obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
obj.insert(std::make_pair(kData, v));
- Post(kRemoteResourceConnectionChangeListener, common::TizenSuccess{response});
+ Post(kRemoteResourceStateChangeListener, common::TizenSuccess{response});
};
+ result = IotconUtils::ConvertIotconError(
+ iotcon_remote_resource_start_monitoring(ptr->handle, MonitoringCallback, ptr.get()));
+ if (!result) {
+ return result;
+ }
return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
}
-common::TizenResult IotconInstance::RemoteResourceUnsetConnectionChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceUnsetResourceStateChangeListener(const picojson::object& args) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
if (!result) {
return result;
}
- ptr->connection_listener = nullptr;
+ ptr->state_listener = nullptr;
return common::TizenSuccess{IotconClientManager::GetInstance().RemoveRemoteResource(ptr)};
}
+common::TizenResult IotconInstance::RemoteResourceGetTimeInterval(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+/* TODO Uncomment when the interface of the function iotcon_remote_resource_get_time_interval is changed
+ FoundRemoteInfoPtr ptr;
+ auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+ if (!res) {
+ LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+ }
+*/
+ int time_interval = 0;
+
+ auto res = IotconUtils::ConvertIotconError(iotcon_remote_resource_get_time_interval(&time_interval));
+ if (!res) {
+ LogAndReturnTizenError(res, ("iotcon_remote_resource_set_time_interval() failed"));
+ }
+
+ return common::TizenSuccess{picojson::value(static_cast<double>(time_interval))};
+}
+
+common::TizenResult IotconInstance::RemoteResourceSetTimeInterval(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+ CHECK_EXIST(args, kTimeInterval);
+
+ int time_interval = static_cast<int>(IotconUtils::GetArg(args, kTimeInterval).get<double>());
+
+/* TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+ FoundRemoteInfoPtr ptr;
+ auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+ if (!res) {
+ LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+ }
+*/
+
+ auto res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_time_interval(time_interval));
+ if (!res) {
+ LogAndReturnTizenError(res, ("iotcon_remote_resource_set_time_interval() failed"));
+ }
+
+ // TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+ // return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
+
+ return common::TizenSuccess{};
+}
+
bool IotconInstance::ResourceFoundCallback(iotcon_remote_resource_h resource,
iotcon_error_e result, void *user_data) {
ScopeLogger();
CallbackData* data = static_cast<CallbackData*>(user_data);
+ if (nullptr == data) {
+ LoggerE("ResourceFoundCallback() failed. Ignoring callback");
+ return IOTCON_FUNC_STOP;
+ }
+
auto ret = IotconUtils::ConvertIotconError(result);
if (!ret) {
data->fun(ret, picojson::value{});
}
data->fun(ret, json_result);
- return IOTCON_FUNC_STOP;
+ return IOTCON_FUNC_CONTINUE;
}
common::TizenResult IotconInstance::ClientFindResource(const picojson::object& args) {
char* host_address = nullptr;
if (args.find(kHostAddress)->second.is<std::string>()) {
host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+ } else {
+ host_address = IOTCON_MULTICAST_ADDRESS;
}
- CHECK_EXIST(args, kResourceType);
- char* resource_type = nullptr;
- if (args.find(kResourceType)->second.is<std::string>()) {
- resource_type = const_cast<char*>(args.find(kResourceType)->second.get<std::string>().c_str());
+ CHECK_EXIST(args, kQuery);
+ iotcon_query_h query = nullptr;
+ const auto& query_obj = args.find(kQuery)->second;
+ if (query_obj.is<picojson::object>()) {
+ auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
}
+ SCOPE_EXIT {
+ if (query) {
+ iotcon_query_destroy(query);
+ }
+ };
CHECK_EXIST(args, kConnectivityType);
iotcon_connectivity_type_e connectivity_type = IotconUtils::ToConnectivityType(
args.find(kConnectivityType)->second.get<std::string>());
- CHECK_EXIST(args, kIsSecure);
- bool is_secure = args.find(kIsSecure)->second.get<bool>();
long long id = GetId(args);
auto response = [this, id](const common::TizenResult& res, const picojson::value& v) {
};
CallbackData* data = new CallbackData{response};
- LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d,\nresource_type: %s,\nis_secure: %d",
- host_address, connectivity_type, resource_type, is_secure);
+ LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d",
+ host_address, connectivity_type);
auto result = IotconUtils::ConvertIotconError(
- iotcon_find_resource(host_address, connectivity_type, resource_type,
- is_secure, ResourceFoundCallback, data));
+ iotcon_find_resource(host_address, connectivity_type, query,
+ ResourceFoundCallback, data));
if (!result) {
delete data;
LogAndReturnTizenError(result);
ScopeLogger();
CallbackData* data = static_cast<CallbackData*>(user_data);
+ if (nullptr == data) {
+ LoggerE("IotconDeviceInfoCb() failed. Ignoring callback");
+ return IOTCON_FUNC_STOP;
+ }
+
picojson::value v{picojson::object{}};
common::TizenResult ret = common::TizenSuccess();
data->fun(ret, v);
delete data;
- return IOTCON_FUNC_STOP;
+ return IOTCON_FUNC_CONTINUE;
}
-common::TizenResult IotconInstance::ClientGetDeviceInfo(const picojson::object& args,
- const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ClientFindDeviceInfo(const picojson::object& args,
+ const common::AsyncToken& token) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
CHECK_EXIST(args, kHostAddress);
- CHECK_EXIST(args, kConnectivityType);
+ char* host_address = nullptr;
+ if (args.find(kHostAddress)->second.is<std::string>()) {
+ host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+ } else {
+ host_address = IOTCON_MULTICAST_ADDRESS;
+ }
+
+ CHECK_EXIST(args, kQuery);
+ iotcon_query_h query = nullptr;
+ const auto& query_obj = args.find(kQuery)->second;
+ if (query_obj.is<picojson::object>()) {
+ auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
+ }
+ SCOPE_EXIT {
+ if (query) {
+ iotcon_query_destroy(query);
+ }
+ };
- std::string host = args.find(kHostAddress)->second.get<std::string>();
+ CHECK_EXIST(args, kConnectivityType);
std::string con_type = args.find(kConnectivityType)->second.get<std::string>();
iotcon_connectivity_type_e con_type_e = IotconUtils::ToConnectivityType(con_type);
CallbackData* data = new CallbackData{SimplePost(token)};
auto result = IotconUtils::ConvertIotconError(
- iotcon_find_device_info(host.c_str(), con_type_e, IotconDeviceInfoCb,
- data));
+ iotcon_find_device_info(host_address, con_type_e, query, IotconDeviceInfoCb, data));
if (!result) {
delete data;
ScopeLogger();
CallbackData* data = static_cast<CallbackData*>(user_data);
+ if (nullptr == data) {
+ LoggerE("IotconPlatformInfoCb() failed. Ignoring callback");
+ return IOTCON_FUNC_STOP;
+ }
+
picojson::value v{picojson::object{}};
common::TizenResult ret = common::TizenSuccess();
data->fun(ret, v);
delete data;
- return IOTCON_FUNC_STOP;
+ return IOTCON_FUNC_CONTINUE;
}
-common::TizenResult IotconInstance::ClientGetPlatformInfo(const picojson::object& args,
- const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ClientFindPlatformInfo(const picojson::object& args,
+ const common::AsyncToken& token) {
ScopeLogger();
CHECK_PRIVILEGE(kPrivilegeIotcon);
CHECK_EXIST(args, kHostAddress);
- CHECK_EXIST(args, kConnectivityType);
+ char* host_address = nullptr;
+ if (args.find(kHostAddress)->second.is<std::string>()) {
+ host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+ } else {
+ host_address = IOTCON_MULTICAST_ADDRESS;
+ }
+
+ CHECK_EXIST(args, kQuery);
+ iotcon_query_h query = nullptr;
+ const auto& query_obj = args.find(kQuery)->second;
+ if (query_obj.is<picojson::object>()) {
+ auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+ if (!result) {
+ LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+ }
+ }
+ SCOPE_EXIT {
+ if (query) {
+ iotcon_query_destroy(query);
+ }
+ };
- std::string host = args.find(kHostAddress)->second.get<std::string>();
+ CHECK_EXIST(args, kConnectivityType);
std::string con_type = args.find(kConnectivityType)->second.get<std::string>();
iotcon_connectivity_type_e con_type_e = IotconUtils::ToConnectivityType(con_type);
CallbackData* data = new CallbackData{SimplePost(token)};
auto result = IotconUtils::ConvertIotconError(
- iotcon_find_platform_info(host.c_str(), con_type_e, IotconPlatformInfoCb,
- data));
+ iotcon_find_platform_info(host_address, con_type_e, query, IotconPlatformInfoCb, data));
if (!result) {
delete data;
CHECK_PRIVILEGE(kPrivilegeIotcon);
CHECK_EXIST(args, kUriPath);
+ CHECK_EXIST(args, kResourceTypes);
+ CHECK_EXIST(args, kResourceInterfaces);
const std::string& uri_path = args.find(kUriPath)->second.get<std::string>();
- const auto& interfaces = IotconUtils::GetArg(args, kResourceInterfaces);
- const auto& resource_interfaces = interfaces.is<picojson::array>() ? interfaces.get<picojson::array>() : picojson::array();
-
const auto& types = IotconUtils::GetArg(args, kResourceTypes);
const auto& resource_types = types.is<picojson::array>() ? types.get<picojson::array>() : picojson::array();
+ const auto& interfaces = IotconUtils::GetArg(args, kResourceInterfaces);
+ const auto& resource_interfaces = interfaces.is<picojson::array>() ? interfaces.get<picojson::array>() : picojson::array();
+
int properties = IotconUtils::GetProperties(args);
ResourceInfoPtr resource{new ResourceInfo()};
return IotconServerManager::GetInstance().DestroyResource(GetId(args));
}
+common::TizenResult IotconInstance::ServerStartPresence(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+ CHECK_EXIST(args, kTimeToLive);
+
+ if (!initialized_) {
+ return LogAndCreateTizenError(AbortError, "Iotcon service not initialized");
+ }
+
+ if (presence_started_) {
+ LoggerD("Iotcon service presence has been already started");
+ return common::TizenSuccess();
+ }
+
+ unsigned int timeToLive = static_cast<unsigned int>(IotconUtils::GetArg(args, kTimeToLive).get<double>());
+
+ auto result = IotconUtils::ConvertIotconError(iotcon_start_presence(timeToLive));
+ if (!result) {
+ LogAndReturnTizenError(result);
+ }
+
+ presence_started_ = true;
+ LoggerD("Iotcon service presence started");
+
+ return result;
+}
+
+common::TizenResult IotconInstance::ServerStopPresence(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+ if (!presence_started_) {
+ LoggerD("Iotcon service presence not started before");
+ return common::TizenSuccess();
+ }
+
+ auto result = IotconUtils::ConvertIotconError(iotcon_stop_presence());
+ if (!result) {
+ LogAndReturnTizenError(result);
+ }
+
+ presence_started_ = false;
+ LoggerD("Iotcon service presence stopped");
+
+ return result;
+}
+
+common::TizenResult IotconInstance::ServerSetDeviceName(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+ CHECK_EXIST(args, kDeviceName);
+
+ if (!initialized_) {
+ return LogAndCreateTizenError(AbortError, "Iotcon service not initialized");
+ }
+
+ const std::string& name = IotconUtils::GetArg(args, kDeviceName).get<std::string>();
+
+ auto result = IotconUtils::ConvertIotconError(iotcon_set_device_name(name.c_str()));
+ if (!result) {
+ LogAndReturnTizenError(result);
+ }
+
+ LoggerD("Iotcon service device name set");
+
+ return result;
+}
+
+common::TizenResult IotconInstance::Initialize(const picojson::object& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+ CHECK_EXIST(args, kFilePath);
+ const auto& filePath = IotconUtils::GetArg(args, kFilePath);
+
+ auto result = IotconUtils::ConvertIotconError(
+ iotcon_initialize(filePath.get<std::string>().c_str()));
+ if (!result) {
+ LogAndReturnTizenError(result);
+ }
+
+ initialized_ = true;
+ LoggerD("Iotcon service initialized");
+
+ return result;
+}
+
common::TizenResult IotconInstance::GetTimeout(const picojson::object& args) {
ScopeLogger();
common::TizenResult ResourceUnsetRequestListener(const picojson::object& args);
common::TizenResult ResponseSend(const picojson::object& args);
common::TizenResult RemoteResourceGetCachedRepresentation(const picojson::object& args);
+ common::TizenResult RemoteResourceGetOptions(const picojson::object& args);
+ common::TizenResult RemoteResourceSetOptions(const picojson::object& args);
common::TizenResult RemoteResourceMethodGet(const picojson::object& args,
const common::AsyncToken& token);
common::TizenResult RemoteResourceMethodPut(const picojson::object& args,
const common::AsyncToken& token);
common::TizenResult RemoteResourceMethodDelete(const picojson::object& args,
const common::AsyncToken& token);
- common::TizenResult RemoteResourceSetStateChangeListener(const picojson::object& args);
- common::TizenResult RemoteResourceUnsetStateChangeListener(const picojson::object& args);
+ common::TizenResult RemoteResourceStartObserving(const picojson::object& args);
+ common::TizenResult RemoteResourceStopObserving(const picojson::object& args);
common::TizenResult RemoteResourceStartCaching(const picojson::object& args);
common::TizenResult RemoteResourceStopCaching(const picojson::object& args);
- common::TizenResult RemoteResourceSetConnectionChangeListener(const picojson::object& args);
- common::TizenResult RemoteResourceUnsetConnectionChangeListener(const picojson::object& args);
+ common::TizenResult RemoteResourceSetResourceStateChangeListener(const picojson::object& args);
+ common::TizenResult RemoteResourceUnsetResourceStateChangeListener(const picojson::object& args);
+ common::TizenResult RemoteResourceGetTimeInterval(const picojson::object& args);
+ common::TizenResult RemoteResourceSetTimeInterval(const picojson::object& args);
common::TizenResult ClientFindResource(const picojson::object& args);
common::TizenResult ClientAddPresenceEventListener(const picojson::object& args);
common::TizenResult ClientRemovePresenceEventListener(const picojson::object& args);
- common::TizenResult ClientGetDeviceInfo(const picojson::object& args,
- const common::AsyncToken& token);
- common::TizenResult ClientGetPlatformInfo(const picojson::object& args,
- const common::AsyncToken& token);
+ common::TizenResult ClientFindDeviceInfo(const picojson::object& args,
+ const common::AsyncToken& token);
+ common::TizenResult ClientFindPlatformInfo(const picojson::object& args,
+ const common::AsyncToken& token);
common::TizenResult ServerCreateResource(const picojson::object& args);
common::TizenResult ServerRemoveResource(const picojson::object& args);
+ common::TizenResult ServerStartPresence(const picojson::object& args);
+ common::TizenResult ServerStopPresence(const picojson::object& args);
+ common::TizenResult ServerSetDeviceName(const picojson::object& args);
+ common::TizenResult Initialize(const picojson::object& args);
common::TizenResult GetTimeout(const picojson::object& args);
common::TizenResult SetTimeout(const picojson::object& args);
common::PostCallback PostForMethodCall(const common::AsyncToken& token, const FoundRemoteInfoPtr& resource);
+
+ private:
+ bool initialized_;
+ bool presence_started_;
};
} // namespace iotcon
}
// handle observer changes
- iotcon_observe_type_e type = IOTCON_OBSERVE_NO_TYPE;
- result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_type(request, &type));
+ iotcon_observe_type_e observe_type = IOTCON_OBSERVE_NO_TYPE;
+ result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_type(request, &observe_type));
if (!result) {
LoggerE("iotcon_request_get_observe_type() failed");
return;
}
- switch (type) {
+ switch (observe_type) {
case IOTCON_OBSERVE_NO_TYPE:
LoggerD("observer did not change");
break;
picojson::value value{picojson::object{}};
auto& obj = value.get<picojson::object>();
- result = IotconUtils::RequestToJson(request, &obj);
-
+ iotcon_request_type_e request_type = IOTCON_REQUEST_UNKNOWN;
+ auto result = IotconUtils::ConvertIotconError(iotcon_request_get_request_type(request, &request_type));
+ if (!result) {
+ LoggerE("iotcon_request_get_request_type() failed");
+ return;
+ }
+ picojson::value request_type_val{IotconUtils::FromRequestType(request_type)};
+ obj.insert(std::make_pair(kRequestType, request_type_val));
+ picojson::value observe_type_val{IotconUtils::FromObserveType(observe_type)};
+ obj.insert(std::make_pair(kObserveType, observe_type_val));
+ picojson::value observe_id_val{static_cast<double>(observer_id)};
+ obj.insert(std::make_pair(kObserverId, observe_id_val));
+
+ picojson::value request_val{picojson::object{}};
+ auto& request_obj = request_val.get<picojson::object>();
+ result = IotconUtils::RequestToJson(request, &request_obj);
if (!result) {
LoggerE("RequestToJson() failed");
return;
}
+ obj.insert(std::make_pair(kRequest, request_val));
+
// create response
iotcon_response_h response = nullptr;
result = IotconUtils::ConvertIotconError(iotcon_response_create(request, &response));
X(IOTCON_RESPONSE_ERROR, "ERROR") \
X(IOTCON_RESPONSE_RESOURCE_CREATED, "RESOURCE_CREATED") \
X(IOTCON_RESPONSE_RESOURCE_DELETED, "RESOURCE_DELETED") \
+ X(IOTCON_RESPONSE_RESOURCE_CHANGED, "RESOURCE_CHANGED") \
X(IOTCON_RESPONSE_SLOW, "SLOW") \
X(IOTCON_RESPONSE_FORBIDDEN, "FORBIDDEN") \
XD(IOTCON_RESPONSE_ERROR, "unknown")
const std::string kResourceInterfaces = "resourceInterfaces";
const std::string kResourceChildren = "resources";
const std::string kUriPath = "uriPath";
-const std::string kStates = "states";
+const std::string kAttributes = "attributes";
const std::string kId = "id";
const std::string kKeepId = "keepId";
const std::string kDeviceId = "deviceId";
+const std::string kDeviceName = "deviceName";
const std::string kHostAddress = "hostAddress";
const std::string kConnectivityType = "connectivityType";
const std::string kObservePolicy = "observePolicy";
const std::string kRepresentation = "representation";
-const std::string kRepresentations = "representations";
+const std::string kChildren = "children";
const std::string kRequestType = "type";
+const std::string kRequest = "request";
const std::string kOptions = "options";
const std::string kQuery = "query";
const std::string kObserverId = "observerId";
const std::string kSupportUrl = "supportUrl";
const std::string kSystemTime = "systemTime";
-const std::string kDeviceName = "deviceName";
const std::string kSpecVersion = "specVersion";
const std::string kOicDeviceId = "oicDeviceId";
const std::string kDataModelVersion = "dataModelVersion";
const std::string kResult = "result";
+const int defRemoteResTimeInterval = 10;
+
using common::TizenResult;
using common::TizenSuccess;
LogAndReturnTizenError(result, ("iotcon_resource_interfaces_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_resource_interfaces_h>::type, void(*)(iotcon_resource_interfaces_h)> ptr{interfaces, &iotcon_resource_interfaces_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_resource_interfaces_h>::type, int(*)(iotcon_resource_interfaces_h)> ptr{interfaces, &iotcon_resource_interfaces_destroy};
for (const auto& iter : i) {
if (!iter.is<std::string>()) {
LogAndReturnTizenError(result, ("iotcon_resource_types_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_resource_types_h>::type, void(*)(iotcon_resource_types_h)> ptr{resource_types, &iotcon_resource_types_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_resource_types_h>::type, int(*)(iotcon_resource_types_h)> ptr{resource_types, &iotcon_resource_types_destroy};
for (const auto& iter : types) {
if (!iter.is<std::string>()) {
result = ConvertIotconError(
iotcon_remote_resource_get_device_id(resource->resource, &resource->device_id));
if (!result) {
- LogAndReturnTizenError(result, ("Gathering host address failed"));
+ LogAndReturnTizenError(result, ("Gathering device id failed"));
+ }
+
+ result = ConvertIotconError(
+ iotcon_remote_resource_get_device_name(resource->resource, &resource->device_name));
+ if (!result) {
+ LogAndReturnTizenError(result, ("Gathering device name failed"));
}
result = ConvertIotconError(
//LogAndReturnTizenError(result, ("Gathering cached representation failed"));
}
+ result = ConvertIotconError(
+ iotcon_remote_resource_get_options(resource->resource, &resource->options));
+ if (!result) {
+ LogAndReturnTizenError(result, ("Gathering options failed"));
+ }
+
return TizenSuccess();
}
FromConnectivityType(remote_res.connectivity_type))));
res->insert(std::make_pair(kHostAddress, picojson::value(remote_res.host_address)));
res->insert(std::make_pair(kDeviceId, picojson::value(remote_res.device_id)));
+ res->insert(std::make_pair(kDeviceName, picojson::value(remote_res.device_name)));
if (remote_res.types) {
picojson::array types;
res->insert(std::make_pair(kRepresentation, repr_json));
}
+ if (remote_res.options) {
+ picojson::array options;
+ result = OptionsToJson(remote_res.options, &options);
+ if (!result) {
+ LogAndReturnTizenError(result, ("OptionsToJson() failed"));
+ }
+ res->insert(std::make_pair(kOptions, picojson::value(options)));
+ }
+
return TizenSuccess();
}
LogAndReturnTizenError(res, ("creating handle failed"));
}
+ // options is optional nullable. if it's not present, just ignore it
+ auto options_it = source.find(kOptions);
+ if (source.end() != options_it) {
+ const auto& options_array = options_it->second.get<picojson::array>();
+ iotcon_options_h options = nullptr;
+ res = IotconUtils::OptionsFromJson(options_array, &options);
+ if (!res) {
+ return res;
+ }
+ res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_options((*ptr)->handle, options));
+ if (!res) {
+ LogAndReturnTizenError(res, ("iotcon_response_set_options() failed"));
+ }
+ }
+
return TizenSuccess();
}
}
{
- // requestType
- iotcon_request_type_e request_type = IOTCON_REQUEST_UNKNOWN;
- auto result = ConvertIotconError(iotcon_request_get_request_type(request, &request_type));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_request_get_request_type() failed"));
- }
- out->insert(std::make_pair(kRequestType, picojson::value{FromRequestType(request_type)}));
- }
-
- {
// options
iotcon_options_h options = nullptr;
auto result = ConvertIotconError(iotcon_request_get_options(request, &options));
}
out->insert(std::make_pair(kQuery, v));
}
-
- {
- // observerId
- int observer_id = -1;
- auto result = ConvertIotconError(iotcon_request_get_observe_id(request, &observer_id));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_request_get_observe_id() failed"));
- }
- out->insert(std::make_pair(kObserverId, picojson::value{static_cast<double>(observer_id)}));
- }
-
- {
- // observeType
- iotcon_observe_type_e observe_type = IOTCON_OBSERVE_NO_TYPE;
- auto result = ConvertIotconError(iotcon_request_get_observe_type(request, &observe_type));
- if (!result) {
- LogAndReturnTizenError(result, ("iotcon_request_get_observe_type() failed"));
- }
- out->insert(std::make_pair(kObserveType, picojson::value{FromObserveType(observe_type)}));
- }
} else {
LoggerW("Request handle is null, ignoring");
}
}
{
- // states
+ // attributes
iotcon_attributes_h attributes = nullptr;
auto result = ConvertIotconError(iotcon_representation_get_attributes(representation, &attributes));
if (!result) {
if (!result) {
LogAndReturnTizenError(result, ("AttributesToJson() failed"));
}
- out->insert(std::make_pair(kStates, v));
+ out->insert(std::make_pair(kAttributes, v));
}
{
- // representations
+ // children
picojson::value v{picojson::array{}};
auto result = ConvertIotconError(iotcon_representation_foreach_children(representation, [](iotcon_representation_h child, void* user_data) -> bool {
auto arr = static_cast<picojson::array*>(user_data);
if (!result) {
LogAndReturnTizenError(result, ("iotcon_representation_foreach_children() failed"));
}
- out->insert(std::make_pair(kRepresentations, v));
+ out->insert(std::make_pair(kChildren, v));
}
} else {
LoggerW("Representation handle is null, ignoring");
if (!result) {
LogAndReturnTizenError(result, ("iotcon_query_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_query_h>::type, void(*)(iotcon_query_h)>
+ std::unique_ptr<std::remove_pointer<iotcon_query_h>::type, int(*)(iotcon_query_h)>
query_ptr(query, &iotcon_query_destroy); // automatically release the memory
{
// resourceType
LogAndReturnTizenError(result, ("iotcon_representation_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, int(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
{
char* uri_path = nullptr;
LogAndReturnTizenError(result, ("iotcon_attributes_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_attributes_h>::type, void(*)(iotcon_attributes_h)> ptr{attributes, &iotcon_attributes_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_attributes_h>::type, int(*)(iotcon_attributes_h)> ptr{attributes, &iotcon_attributes_destroy};
for (const auto& property : s) {
const auto& key = property.first;
LogAndReturnTizenError(result, ("iotcon_list_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_list_h>::type, void(*)(iotcon_list_h)> ptr{list, &iotcon_list_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_list_h>::type, int(*)(iotcon_list_h)> ptr{list, &iotcon_list_destroy};
int position = 0;
default:
// should not happen
LoggerE("Unexpected type: %d", type);
- return common::UnknownError("Unexpected list type");
+ return common::AbortError("Unexpected list type");
}
}
LogAndReturnTizenError(result, ("iotcon_options_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_options_h>::type, void(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_options_h>::type, int(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy};
// we ignore values with incorrect types
// TODO: should we convert them in JS?
LogAndReturnTizenError(result, ("iotcon_representation_create() failed"));
}
- std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
+ std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, int(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
{
const auto& uri_path = r.find(kUriPath);
}
{
- const auto& states = r.find(kStates);
+ const auto& states = r.find(kAttributes);
if (r.end() != states && states->second.is<picojson::object>()) {
iotcon_attributes_h s = nullptr;
}
{
- const auto& representations = r.find(kRepresentations);
- if (r.end() != representations && representations->second.is<picojson::array>()) {
- for (const auto& js_child : representations->second.get<picojson::array>()) {
+ const auto& children = r.find(kChildren);
+ if (r.end() != children && children->second.is<picojson::array>()) {
+ for (const auto& js_child : children->second.get<picojson::array>()) {
if (js_child.is<picojson::object>()) {
iotcon_representation_h child = nullptr;
LogAndReturnTizenError(result, ("iotcon_representation_add_child() failed"));
}
} else {
- return LogAndCreateTizenError(TypeMismatchError, "The Representation.representations attribute needs to be an array of Representation objects.");
+ return LogAndCreateTizenError(TypeMismatchError, "The Representation.children attribute needs to be an array of Representation objects.");
}
}
}
case IOTCON_ERROR_NOT_SUPPORTED:
return common::NotSupportedError(error);
+ case IOTCON_ERROR_NO_DATA:
case IOTCON_ERROR_INVALID_PARAMETER:
return common::InvalidValuesError(error);
- case IOTCON_ERROR_NO_DATA:
- return common::NotFoundError(error);
-
case IOTCON_ERROR_TIMEOUT:
return common::TimeoutError(error);
extern const std::string kResourceInterfaces;
extern const std::string kResourceChildren;
extern const std::string kUriPath;
-extern const std::string kStates;
+extern const std::string kAttributes;
extern const std::string kId;
extern const std::string kKeepId;
extern const std::string kDeviceId;
+extern const std::string kDeviceName;
extern const std::string kHostAddress;
extern const std::string kConnectivityType;
extern const std::string kResourceType;
extern const std::string kOptions;
extern const std::string kQuery;
extern const std::string kObservePolicy;
+extern const std::string kRequestType;
+extern const std::string kRequest;
+extern const std::string kObserveType;
+extern const std::string kObserverId;
+
+extern const int defRemoteResTimeInterval;
class ResourceInfo;
class PresenceEvent;
iotcon_connectivity_type_e connectivity_type;
char* host_address;
char* device_id;
+ char* device_name;
iotcon_resource_types_h types;
iotcon_resource_interfaces_h ifaces;
uint8_t properties; // to check if observable
RemoteResourceInfo() :
resource(nullptr), uri_path(nullptr),
connectivity_type(IOTCON_CONNECTIVITY_ALL), host_address(nullptr),
- device_id(nullptr), types(nullptr), ifaces(0),
+ device_id(nullptr), device_name(nullptr), types(nullptr), ifaces(0),
properties(0), options(nullptr), representation(nullptr) {}
~RemoteResourceInfo() {
//according to native description, must not release any handles
iotcon_remote_resource_h handle;
short ref_count; // counter for registered listeners for this handle
//TODO add listeners for each type
- common::PostCallback connection_listener;
+ common::PostCallback state_listener;
common::PostCallback observe_listener;
+ common::PostCallback cache_change_listener;
FoundRemoteInfo() :
id(0), handle(nullptr), ref_count(1) {} //initialize with 1 (struct is created, so it
//mean that some listener would be created)
memset(strDBName, 0x00, sizeof(strDBName));
snprintf(strDBName, sizeof(strDBName), "%s/%s",
- tzplatform_getenv(TZ_SYS_DB), MSG_DB_NAME);
+ tzplatform_getenv(TZ_SYS_GLOBALUSER_DB), MSG_DB_NAME);
// this should match MSGFW_DB_NAME defined in msg-service/include/utils/MsgSqliteWrapper.h
SLoggerD("Using database: [%s]", strDBName);
'secureelement_extension.h',
'secureelement_instance.cc',
'secureelement_instance.h',
- 'secureelement_seservice.cc',
- 'secureelement_seservice.h',
- 'secureelement_reader.cc',
- 'secureelement_reader.h',
- 'secureelement_session.cc',
- 'secureelement_session.h',
- 'secureelement_channel.cc',
- 'secureelement_channel.h',
],
'includes': [
'../common/pkg-config.gypi',
],
'conditions': [
[ 'tizen == 1', {
- 'variables': { 'packages': ['smartcard-service', 'smartcard-service-common'] },
+ 'variables': { 'packages': ['capi-network-smartcard'] },
}],
],
},
console.log('SEReader_isPresent error: ' + native_.getErrorObject(result));
return false;
} else {
- return native_.getResultObject(result).isPresent;
+ return native_.getResultObject(result);
}
}},
_handle: { configurable: false,
throw native_.getErrorObject(result);
}
- return native_.getResultObject(result).name;
+ return native_.getResultObject(result);
};
Reader.prototype.openSession = function() {
console.log('SESession_isClosed error: ' + native_.getErrorObject(result));
return true;
} else {
- return native_.getResultObject(result).isClosed;
+ return native_.getResultObject(result);
}
}
},
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "secureelement_channel.h"
-
-using namespace smartcard_service_api;
-
-namespace extension {
-namespace secureelement {
-
-void SEChannel::close() {
- LoggerD("Entered");
- if (m_channel_ptr && !m_channel_ptr->isClosed()) {
- m_channel_ptr->closeSync();
- }
-}
-
-
-ByteArray SEChannel::transmit(const picojson::array& v_command) {
- LoggerD("Entered");
- ByteArray response;
- if ( m_channel_ptr) {
- size_t v_command_size = v_command.size();
- uint8_t* command = new uint8_t[v_command_size];
- for (size_t i = 0; i < v_command_size; i++) {
- command[i] = (uint8_t) static_cast<long>(v_command[i].get<double>());
- }
- ByteArray ba_command(command, v_command.size());
- delete [] command;
- m_channel_ptr->transmitSync( ba_command, response);
- }
- return response;
-}
-
-
-ByteArray SEChannel::getSelectResponse() {
- LoggerD("Entered");
- ByteArray response;
- if ( m_channel_ptr) {
- response = m_channel_ptr->getSelectResponse();
- }
- return response;
-}
-
-} // secureelement
-} // extension
#include "secureelement/secureelement_instance.h"
-#include <SEService.h>
-#include <Reader.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "common/task-queue.h"
-#include "common/tools.h"
+#include <thread>
+#include <smartcard.h>
-#include "secureelement_reader.h"
-#include "secureelement_session.h"
-#include "secureelement_channel.h"
+#include "common/tools.h"
+#include "common/scope_exit.h"
namespace extension {
namespace secureelement {
-using namespace common;
-using namespace smartcard_service_api;
+using common::TizenResult;
+using common::TizenSuccess;
namespace {
const std::string kPrivilegeSecureElement = "http://tizen.org/privilege/secureelement";
+
+const std::string kHandle = "handle";
+const std::string kIsBasicChannel = "isBasicChannel";
+const std::string kAid = "aid";
+const std::string kAction = "action";
+const std::string kCommand = "command";
+const std::string kListenerId = "listenerId";
+const std::string kListener = "SecureElementChangeListener";
+const std::string kReady = "onSEReady";
+const std::string kNotReady = "onSENotReady";
+
+TizenResult ConvertErrorCode(int error) {
+ switch (error) {
+ case SMARTCARD_ERROR_NONE:
+ return TizenSuccess();
+ case SMARTCARD_ERROR_INVALID_PARAMETER:
+ return common::InvalidValuesError(error);
+ case SMARTCARD_ERROR_IO_ERROR:
+ return common::IoError(error);
+ case SMARTCARD_ERROR_ILLEGAL_STATE:
+ case SMARTCARD_ERROR_CHANNEL_NOT_AVAILABLE:
+ return common::InvalidStateError(error);
+ case SMARTCARD_ERROR_NO_SUCH_ELEMENT:
+ return common::NotFoundError(error);
+ case SMARTCARD_ERROR_GENERAL:
+ case SMARTCARD_ERROR_ILLEGAL_REFERENCE:
+ case SMARTCARD_ERROR_OPERATION_NOT_SUPPORTED:
+ case SMARTCARD_ERROR_PERMISSION_DENIED:
+ case SMARTCARD_ERROR_NOT_INITIALIZED:
+ case SMARTCARD_ERROR_NOT_SUPPORTED:
+ default:
+ return common::UnknownError(error);
+ }
}
-SecureElementInstance::SecureElementInstance()
- : service_(*this) {
- LoggerD("Entered");
+void SecureElementEventCb(int reader, smartcard_reader_event_type_e event_type, void *user_data) {
+ ScopeLogger();
+
+ //TODO What action should be performed in case of SMARTCARD_READER_EVENT_TYPE_IO_ERROR event
+ if (SMARTCARD_READER_EVENT_TYPE_INSERTED != event_type &&
+ SMARTCARD_READER_EVENT_TYPE_REMOVED != event_type) {
+ LoggerD("Incorrect event type");
+ return;
+ }
+
+ SecureElementInstance* instance = static_cast<SecureElementInstance*>(user_data);
+ if (!instance) {
+ LoggerD("user data is null");
+ return;
+ }
+
+ picojson::value result{picojson::object{}};
+ auto& obj = result.get<picojson::object>();
- using std::placeholders::_1;
- using std::placeholders::_2;
+ std::string action = SMARTCARD_READER_EVENT_TYPE_INSERTED == event_type ? kReady : kNotReady;
+
+ obj.insert(std::make_pair(kAction, picojson::value(action)));
+ obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(reader))));
+ obj.insert(std::make_pair(kListenerId, picojson::value(kListener)));
+
+ instance->Instance::PostMessage(instance, result.serialize().c_str());
+}
+
+} //namespace
+
+SecureElementInstance::SecureElementInstance() :
+ is_initialized_(false),
+ is_listener_set_(false) {
+ ScopeLogger();
+
+ using std::placeholders::_1;
+ using std::placeholders::_2;
#define REGISTER_SYNC(c,x) \
- RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
-
- REGISTER_SYNC("SEService_registerSEListener", RegisterSEListener);
- REGISTER_SYNC("SEService_unregisterSEListener", UnregisterSEListener);
- REGISTER_SYNC("SEService_shutdown", Shutdown);
- REGISTER_SYNC("SEReader_getName", GetName);
- REGISTER_SYNC("SEReader_isPresent", IsPresent);
- REGISTER_SYNC("SEReader_closeSessions", CloseSessions);
- REGISTER_SYNC("SESession_getATR", GetATR);
- REGISTER_SYNC("SESession_isClosed", IsSessionClosed);
- REGISTER_SYNC("SESession_close", CloseSession);
- REGISTER_SYNC("SESession_closeChannels", CloseChannels);
- REGISTER_SYNC("SEChannel_close", CloseChannel);
- REGISTER_SYNC("SEChannel_getSelectResponse", GetSelectResponse);
+ RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1));
+
+ REGISTER_SYNC("SEService_registerSEListener", RegisterSEListener);
+ REGISTER_SYNC("SEService_unregisterSEListener", UnregisterSEListener);
+ REGISTER_SYNC("SEService_shutdown", Shutdown);
+ REGISTER_SYNC("SEReader_getName", GetName);
+ REGISTER_SYNC("SEReader_isPresent", IsPresent);
+ REGISTER_SYNC("SEReader_closeSessions", CloseSessions);
+ REGISTER_SYNC("SESession_getATR", GetATR);
+ REGISTER_SYNC("SESession_isClosed", IsSessionClosed);
+ REGISTER_SYNC("SESession_close", CloseSession);
+ REGISTER_SYNC("SESession_closeChannels", CloseChannels);
+ REGISTER_SYNC("SEChannel_close", CloseChannel);
+ REGISTER_SYNC("SEChannel_getSelectResponse", GetSelectResponse);
#undef REGISTER_SYNC
#define REGISTER(c,x) \
- RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
+ RegisterHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
- REGISTER("SEService_getReaders", GetReaders);
- REGISTER("SEReader_openSession", OpenSession);
- REGISTER("SESession_openBasicChannel", OpenBasicChannel);
- REGISTER("SESession_openLogicalChannel", OpenLogicalChannel);
- REGISTER("SEChannel_transmit", Transmit);
+ REGISTER("SEService_getReaders", GetReaders);
+ REGISTER("SEReader_openSession", OpenSession);
+ REGISTER("SESession_openBasicChannel", OpenBasicChannel);
+ REGISTER("SESession_openLogicalChannel", OpenLogicalChannel);
+ REGISTER("SEChannel_transmit", Transmit);
#undef REGISTER
+
+ if (SMARTCARD_ERROR_NONE == smartcard_initialize()) {
+ is_initialized_ = true;
+ }
}
SecureElementInstance::~SecureElementInstance() {
+ ScopeLogger();
+
+ UnregisterListener();
+ Deinitialize();
}
-void SecureElementInstance::GetReaders(const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+// Service methods
+TizenResult SecureElementInstance::GetReaders(picojson::object const& args, const common::AsyncToken& token) {
+ ScopeLogger();
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
- double callback_id = 0.0;
- if (args.contains("callbackId")) {
- callback_id = args.get("callbackId").get<double>();
- }
+ auto get_readers = [this](const common::AsyncToken& token) -> void {
+ TizenResult result = TizenSuccess();
+
+ int* readers = nullptr;
+ int count = 0;
+
+ int ret = smartcard_get_readers(&readers, &count);
+ SCOPE_EXIT {
+ free(readers);
+ };
+
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LoggerE("smartcard_get_readers() failed");
+ result = ConvertErrorCode(ret);
+ } else {
+ picojson::value response{picojson::array{}};
+ auto& array = response.get<picojson::array>();
+ bool is_present = false;
+
+ for (int i = 0; i < count; i++) {
+ ret = smartcard_reader_is_secure_element_present(readers[i], &is_present);
+ if (SMARTCARD_ERROR_NONE == ret && is_present) {
+ array.push_back(picojson::value(static_cast<double>(readers[i])));
+ }
+ }
+
+ result = TizenSuccess(response);
+ }
+
+ this->Post(token, result);
+ };
- service_.GetReaders(callback_id);
- ReportSuccess(out);
+ std::thread(get_readers, token).detach();
+
+ return TizenSuccess();
}
-void SecureElementInstance::RegisterSEListener(const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+TizenResult SecureElementInstance::RegisterSEListener(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ int ret = smartcard_reader_set_event_cb(SecureElementEventCb, this);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_set_event_cb() failed"));
+ }
+
+ is_listener_set_ = true;
- service_.RegisterSEListener();
- ReportSuccess(out);
+ return TizenSuccess();
}
-void SecureElementInstance::UnregisterSEListener(
- const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+TizenResult SecureElementInstance::UnregisterListener() {
+ ScopeLogger();
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ if (is_listener_set_) {
+ int ret = smartcard_reader_unset_event_cb();
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_unset_event_cb() failed"));
+ }
- service_.UnregisterSEListener();
- ReportSuccess(out);
+ is_listener_set_ = false;
+ }
+
+ return TizenSuccess();
}
-void SecureElementInstance::Shutdown(const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+TizenResult SecureElementInstance::UnregisterSEListener(picojson::object const& args) {
+ ScopeLogger();
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
- service_.Shutdown();
- ReportSuccess(out);
+ return UnregisterListener();
}
-void SecureElementInstance::GetName(
- const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+TizenResult SecureElementInstance::Deinitialize() {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ if (is_initialized_) {
+ int ret = smartcard_deinitialize();
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_deinitialize() failed"));
+ }
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ is_initialized_ = false;
+ }
- Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
- SEReader seReader(reader_ptr);
- picojson::value result = seReader.getName();
- ReportSuccess(result, out);
+ return TizenSuccess();
}
-void SecureElementInstance::IsPresent(
- const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+TizenResult SecureElementInstance::Shutdown(picojson::object const& args) {
+ ScopeLogger();
- Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
- SEReader seReader(reader_ptr);
- picojson::value result = seReader.isPresent();
- ReportSuccess(result, out);
+ UnregisterListener();
+ return Deinitialize();
}
-void SecureElementInstance::CloseSessions(
- const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
+// Reader methods
+TizenResult SecureElementInstance::GetName(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+ char* name = nullptr;
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ int ret = smartcard_reader_get_name(reader, &name);
+ SCOPE_EXIT {
+ free(name);
+ };
- Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
- SEReader seReader(reader_ptr);
- seReader.closeSessions();
- ReportSuccess(out);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_get_name() failed"));
+ }
+
+ return TizenSuccess(picojson::value(name));
}
-void SecureElementInstance::CloseChannel( const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+TizenResult SecureElementInstance::IsPresent(picojson::object const& args) {
+ ScopeLogger();
+
+ int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+ bool is_present = false;
+
+ int ret = smartcard_reader_is_secure_element_present(reader, &is_present);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret),
+ ("smartcard_reader_is_secure_element_present() failed"));
+ }
- ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
- SEChannel seChannel(channel_ptr);
- seChannel.close();
- ReportSuccess(out);
+ return TizenSuccess(picojson::value(is_present));
}
-void SecureElementInstance::GetSelectResponse( const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+TizenResult SecureElementInstance::OpenSession(picojson::object const& args, const common::AsyncToken& token) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+ auto open_session = [this, reader](const common::AsyncToken& token) -> void {
+ TizenResult result = TizenSuccess();
+ int session = 0;
- ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
- SEChannel seChannel(channel_ptr);
+ int ret = smartcard_reader_open_session(reader, &session);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LoggerE("smartcard_reader_open_session() failed");
+ result = ConvertErrorCode(ret);
+ } else {
+ picojson::value response{picojson::object{}};
+ auto& obj = response.get<picojson::object>();
- ByteArray select_response = seChannel.getSelectResponse();
- picojson::value result = picojson::value(picojson::array());
- picojson::array& arr = result.get<picojson::array>();
- size_t select_response_size = select_response.size();
- for (size_t i = 0; i < select_response_size; i++) {
- arr.push_back(picojson::value(static_cast<double>(select_response[i])));
+ obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(session))));
+ result = TizenSuccess(response);
}
- ReportSuccess( result, out);
+
+ this->Post(token, result);
+ };
+
+ std::thread(open_session, token).detach();
+
+ return TizenSuccess();
}
-void SecureElementInstance::OpenSession(
- const picojson::value& args, picojson::object& out) {
- LoggerD("Entered");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
- const double callback_id = args.get("callbackId").get<double>();
- Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
-
- auto open_session = [this, reader_ptr](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Opening session");
- try {
- SEReader seReader(reader_ptr);
- picojson::value result = seReader.openSession();
- ReportSuccess(result, response->get<picojson::object>());
- } catch (const ErrorIO& err) {
- LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalState& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalParameter& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
- } catch (const ErrorSecurity& err) {
- LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
- } catch (const ExceptionBase& err) {
- LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
- }
- };
+TizenResult SecureElementInstance::CloseSessions(picojson::object const& args) {
+ ScopeLogger();
- auto open_session_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Getting response");
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
- picojson::object& obj = response->get<picojson::object>();
- obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
- Instance::PostMessage(this, response->serialize().c_str());
- };
+ int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
- auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ int ret = smartcard_reader_close_sessions(reader);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_close_sessions() failed"));
+ }
- TaskQueue::GetInstance().Queue<picojson::value>(
- open_session,
- open_session_response,
- data);
+ return TizenSuccess();
}
// Session functions
-void SecureElementInstance::OpenBasicChannel( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
- const double callback_id = args.get("callbackId").get<double>();
- const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-
- auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Opening basic channel");
- try {
- SESession seSession(session_ptr);
- picojson::value result = seSession.openBasicChannel(v_aid);
- ReportSuccess(result, response->get<picojson::object>());
- } catch (const ErrorIO& err) {
- LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalState& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalParameter& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
- } catch (const ErrorSecurity& err) {
- LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
- } catch (const ExceptionBase& err) {
- LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
- }
- };
+TizenResult SecureElementInstance::IsBasicChannel(int channel, picojson::value& val) {
+ ScopeLogger();
- auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Getting response");
- picojson::object& obj = response->get<picojson::object>();
- obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
- Instance::PostMessage(this, response->serialize().c_str());
- };
+ bool is_basic = false;
+ int ret = smartcard_channel_is_basic_channel(channel, &is_basic);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_channel_is_basic_channel() failed"));
+ }
- auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ auto& obj = val.get<picojson::object>();
+ obj.insert(std::make_pair(kIsBasicChannel, picojson::value(is_basic)));
- TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+ return TizenSuccess(val);
}
+TizenResult SecureElementInstance::OpenBasicChannel(picojson::object const& args, const common::AsyncToken& token) {
+ ScopeLogger();
-void SecureElementInstance::OpenLogicalChannel( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
- const double callback_id = args.get("callbackId").get<double>();
- const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-
- auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Opening basic channel");
- try {
- SESession seSession(session_ptr);
- picojson::value result = seSession.openLogicalChannel(v_aid);
- ReportSuccess(result, response->get<picojson::object>());
- } catch (const ErrorIO& err) {
- LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalState& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
- } catch (const ErrorIllegalParameter& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
- } catch (const ErrorSecurity& err) {
- LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
- } catch (const ExceptionBase& err) {
- LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
- }
- };
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+ const picojson::array v_aid = args.find(kAid)->second.get<picojson::array>();
- auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Getting response");
- picojson::object& obj = response->get<picojson::object>();
- obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
- Instance::PostMessage(this, response->serialize().c_str());
+ auto open_basic_channel = [this, session, v_aid](const common::AsyncToken& token) -> void {
+ TizenResult result = TizenSuccess();
+ int channel = 0;
+ unsigned char P2 = 0;
+
+ size_t v_aid_size = v_aid.size();
+ unsigned char* aid = new unsigned char[v_aid_size];
+ SCOPE_EXIT {
+ delete [] aid;
};
- auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ for (size_t i = 0; i < v_aid_size; i++) {
+ aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
+ }
+
+ int ret = smartcard_session_open_basic_channel(session, aid, v_aid_size, P2, &channel);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LoggerE("smartcard_session_open_basic_channel() failed");
+ result = ConvertErrorCode(ret);
+ } else {
+ picojson::value response{picojson::object{}};
+ auto& obj = response.get<picojson::object>();
+
+ obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(channel))));
+ result = IsBasicChannel(channel, response);
+ }
+
+ this->Post(token, result);
+ };
+
+ std::thread(open_basic_channel, token).detach();
- TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+ return TizenSuccess();
}
+TizenResult SecureElementInstance::OpenLogicalChannel(picojson::object const& args, const common::AsyncToken& token) {
+ ScopeLogger();
-void SecureElementInstance::GetATR( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
- SESession seSession(session_ptr);
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+ const picojson::array v_aid = args.find(kAid)->second.get<picojson::array>();
- ByteArray atr_result = seSession.getATR();
- picojson::value result = picojson::value(picojson::array());
- picojson::array& arr = result.get<picojson::array>();
- size_t atr_result_size = atr_result.size();
- for (size_t i = 0; i < atr_result_size; i++) {
- arr.push_back(picojson::value(static_cast<double>(atr_result[i])));
+ auto open_basic_logical = [this, session, v_aid](const common::AsyncToken& token) -> void {
+ TizenResult result = TizenSuccess();
+ int channel = 0;
+ unsigned char P2 = 0;
+
+ size_t v_aid_size = v_aid.size();
+ unsigned char* aid = new unsigned char[v_aid_size];
+ SCOPE_EXIT {
+ delete [] aid;
+ };
+
+ for (size_t i = 0; i < v_aid_size; i++) {
+ aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
}
- ReportSuccess( result, out);
+
+ int ret = smartcard_session_open_logical_channel(session, aid, v_aid_size, P2, &channel);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LoggerE("smartcard_session_open_logical_channel() failed");
+ result = ConvertErrorCode(ret);
+ } else {
+ picojson::value response{picojson::object{}};
+ auto& obj = response.get<picojson::object>();
+
+ obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(channel))));
+ result = IsBasicChannel(channel, response);
+ }
+
+ this->Post(token, result);
+ };
+
+ std::thread(open_basic_logical, token).detach();
+
+ return TizenSuccess();
}
+TizenResult SecureElementInstance::GetATR(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+ int length = 0;
+ unsigned char* atr = nullptr;
+
+ int ret = smartcard_session_get_atr(session, &atr, &length);
+ SCOPE_EXIT {
+ free(atr);
+ };
-void SecureElementInstance::IsSessionClosed( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
- SESession seSession(session_ptr);
- picojson::value result = seSession.isClosed();
- ReportSuccess( result, out);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_get_atr() failed"));
+ }
+
+ picojson::value response{picojson::array{}};
+ auto& array = response.get<picojson::array>();
+
+ for (int i = 0; i < length; i++) {
+ array.push_back(picojson::value(static_cast<double>(atr[i])));
+ }
+
+ return TizenSuccess(response);
}
+TizenResult SecureElementInstance::IsSessionClosed(picojson::object const& args) {
+ ScopeLogger();
+
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+ bool is_closed = false;
-void SecureElementInstance::CloseSession( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ int ret = smartcard_session_is_closed(session, &is_closed);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_is_closed() failed"));
+ }
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
- SESession seSession(session_ptr);
- seSession.close();
- ReportSuccess(out);
+ return TizenSuccess(picojson::value(is_closed));
}
+TizenResult SecureElementInstance::CloseSession(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
-void SecureElementInstance::CloseChannels( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
- Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
- SESession seSession(session_ptr);
- seSession.closeChannels();
- ReportSuccess(out);
+ int ret = smartcard_session_close(session);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_close() failed"));
+ }
+
+ return TizenSuccess();
}
-void SecureElementInstance::Transmit( const picojson::value& args, picojson::object& out) {
- LoggerD("Enter");
- CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
- const double callback_id = args.get("callbackId").get<double>();
- const picojson::array v_command = args.get("command").get<picojson::value::array>();
- ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
-
- auto open = [this, v_command, channel_ptr](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Transmit APDDU command to secure element");
- try {
- SEChannel seChannel(channel_ptr);
- ByteArray transmit_response = seChannel.transmit(v_command);
- picojson::value result = picojson::value(picojson::array());
- picojson::array& arr = result.get<picojson::array>();
- size_t transmit_response_size = transmit_response.size();
- for (size_t i = 0; i < transmit_response_size; i++) {
- arr.push_back(picojson::value(static_cast<double>(transmit_response[i])));
- }
- ReportSuccess( result, response->get<picojson::object>());
- } catch (const ErrorIO& err) {
- LogAndReportError(PlatformResult(ErrorCode::IO_ERR, "Failed to transmit command."), &response->get<picojson::object>());
- } catch (const ErrorIllegalState& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Failed to transmit command."), &response->get<picojson::object>());
- } catch (const ErrorIllegalParameter& err) {
- LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to transmit command."), &response->get<picojson::object>());
- } catch (const ErrorSecurity& err) {
- LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR, "Failed to transmit command."), &response->get<picojson::object>());
- } catch (const ExceptionBase& err) {
- LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to transmit command."), &response->get<picojson::object>());
- }
+TizenResult SecureElementInstance::CloseChannels(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+ int ret = smartcard_session_close_channels(session);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_close_channels() failed"));
+ }
+
+ return TizenSuccess();
+}
+
+// Channel methods
+TizenResult SecureElementInstance::CloseChannel(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+ int ret = smartcard_channel_close(channel);
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_channel_close() failed"));
+ }
+
+ return TizenSuccess();
+}
+
+TizenResult SecureElementInstance::Transmit(picojson::object const& args, const common::AsyncToken& token) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+ const auto& v_cmd = args.find(kCommand)->second.get<picojson::array>();
+
+ auto transmit = [this, channel, v_cmd](const common::AsyncToken& token) -> void {
+ TizenResult result = TizenSuccess();
+
+ size_t v_cmd_size = v_cmd.size();
+ unsigned char* cmd = new unsigned char[v_cmd_size];
+ SCOPE_EXIT {
+ delete [] cmd;
};
- auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
- LoggerD("Getting response");
- picojson::object& obj = response->get<picojson::object>();
- obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
- Instance::PostMessage(this, response->serialize().c_str());
+ for (size_t i = 0; i < v_cmd_size; i++) {
+ cmd[i] = static_cast<unsigned char>(v_cmd[i].get<double>());
+ }
+
+ int length = 0;
+ unsigned char* response = nullptr;
+
+ int ret = smartcard_channel_transmit(channel, cmd, v_cmd_size, &response, &length);
+ SCOPE_EXIT {
+ free(response);
};
- auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LoggerE("smartcard_channel_transmit() failed");
+ result = ConvertErrorCode(ret);
+ } else {
+ picojson::value response_v{picojson::array{}};
+ auto& array = response_v.get<picojson::array>();
+
+ for (int i = 0; i < length; i++) {
+ array.push_back(picojson::value(static_cast<double>(response[i])));
+ }
+
+ result = TizenSuccess(response_v);
+ }
+
+ this->Post(token, result);
+ };
+
+ std::thread(transmit, token).detach();
+
+ return TizenSuccess();
+}
+
+TizenResult SecureElementInstance::GetSelectResponse(picojson::object const& args) {
+ ScopeLogger();
+
+ CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+ int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+ int length = 0;
+ unsigned char* select_response = nullptr;
+
+ int ret = smartcard_channel_get_select_response(channel, &select_response, &length);
+ SCOPE_EXIT {
+ free(select_response);
+ };
+
+ if (SMARTCARD_ERROR_NONE != ret) {
+ LogAndReturnTizenError(ConvertErrorCode(ret),
+ ("smartcard_channel_get_select_response() failed"));
+ }
+
+ picojson::value response{picojson::array{}};
+ auto& array = response.get<picojson::array>();
+
+ for (int i = 0; i < length; i++) {
+ array.push_back(picojson::value(static_cast<double>(select_response[i])));
+ }
- TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+ return TizenSuccess(response);
}
} // namespace secureelement
#ifndef SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
#define SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
-#include "common/extension.h"
-#include "secureelement_seservice.h"
+#include "common/tizen_instance.h"
namespace extension {
namespace secureelement {
-class SecureElementInstance: public common::ParsedInstance {
+class SecureElementInstance: public common::TizenInstance {
public:
SecureElementInstance();
virtual ~SecureElementInstance();
private:
- /* SEService methods */
- void GetReaders(const picojson::value& args, picojson::object& out);
- void RegisterSEListener(const picojson::value& args, picojson::object& out);
- void UnregisterSEListener(const picojson::value& args, picojson::object& out);
- void Shutdown(const picojson::value& args, picojson::object& out);
+ /* Service methods */
+ common::TizenResult GetReaders(picojson::object const& args, const common::AsyncToken& token);
+ common::TizenResult RegisterSEListener(picojson::object const& args);
+ common::TizenResult UnregisterSEListener(picojson::object const& args);
+ common::TizenResult Shutdown(picojson::object const& args);
/* Reader methods */
- void GetName(const picojson::value& args, picojson::object& out);
- void IsPresent(const picojson::value& args, picojson::object& out);
- void OpenSession(const picojson::value& args, picojson::object& out);
- void CloseSessions(const picojson::value& args, picojson::object& out);
+ common::TizenResult GetName(picojson::object const& args);
+ common::TizenResult IsPresent(picojson::object const& args);
+ common::TizenResult OpenSession(picojson::object const& args, const common::AsyncToken& token);
+ common::TizenResult CloseSessions(picojson::object const& args);
/* Session methods */
- void OpenBasicChannel(const picojson::value& args, picojson::object& out);
- void OpenLogicalChannel(const picojson::value& args, picojson::object& out);
- void GetATR(const picojson::value& args, picojson::object& out);
- void IsSessionClosed(const picojson::value& args, picojson::object& out);
- void CloseSession(const picojson::value& args, picojson::object& out);
- void CloseChannels(const picojson::value& args, picojson::object& out);
+ common::TizenResult IsBasicChannel(int channel, picojson::value& val);
+ common::TizenResult OpenBasicChannel(picojson::object const& args, const common::AsyncToken& token);
+ common::TizenResult OpenLogicalChannel(picojson::object const& args, const common::AsyncToken& token);
+ common::TizenResult GetATR(picojson::object const& args);
+ common::TizenResult IsSessionClosed(picojson::object const& args);
+ common::TizenResult CloseSession(picojson::object const& args);
+ common::TizenResult CloseChannels(picojson::object const& args);
/* Channel methods */
- void CloseChannel(const picojson::value& args, picojson::object& out);
- void Transmit(const picojson::value& args, picojson::object& out);
- void GetSelectResponse(const picojson::value& args, picojson::object& out);
+ common::TizenResult CloseChannel(picojson::object const& args);
+ common::TizenResult Transmit(picojson::object const& args, const common::AsyncToken& token);
+ common::TizenResult GetSelectResponse(picojson::object const& args);
- SEService service_;
+ common::TizenResult Deinitialize();
+ common::TizenResult UnregisterListener();
+
+ bool is_initialized_;
+ bool is_listener_set_;
};
} // namespace secureelement
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "secureelement_reader.h"
-
-#include <Session.h>
-#include <Reader.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-
-using namespace smartcard_service_api;
-using namespace std;
-
-namespace extension {
-namespace secureelement {
-
-
-picojson::value SEReader::getName() {
- LoggerD("Entered");
-
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
-
- if(m_reader) {
- obj.insert(std::make_pair("name", picojson::value(m_reader->getName())));
- }
-
- return result;
-}
-
-picojson::value SEReader::isPresent() {
- LoggerD("Entered");
-
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
-
- if(m_reader) {
- obj.insert(std::make_pair("isPresent", picojson::value(m_reader->isSecureElementPresent())));
- }
-
- return result;
-}
-
-picojson::value SEReader::openSession() {
- LoggerD("Entered");
-
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
-
- if(m_reader) {
- Session *session_ptr = static_cast<Session*>(m_reader->openSessionSync());
-
- obj.insert(std::make_pair("handle", picojson::value((double) (long) session_ptr)));
- obj.insert(std::make_pair("isClosed", picojson::value(session_ptr->isClosed())));
- }
-
- return result;
-}
-
-void SEReader::closeSessions() {
- LoggerD("Entered");
-
- if(m_reader) {
- m_reader->closeSessions();
- }
-}
-
-}// secureelement
-}// extension
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "secureelement/secureelement_seservice.h"
-
-#include "common/logger.h"
-#include "common/platform_result.h"
-#include "common/task-queue.h"
-#include "common/tools.h"
-
-
-#include "secureelement/secureelement_instance.h"
-
-using namespace smartcard_service_api;
-using namespace common;
-using namespace tools;
-
-namespace extension {
-namespace secureelement {
-
-namespace {
-const int SE_INSERTED = 1;
-const int SE_REMOVED = 2;
-}
-
-class SEServiceEventHandler : public SEServiceListener {
- void serviceConnected(SEServiceHelper *service, void *context) {
- LoggerD("Entered");
- if (context) {
- (static_cast<SEService*>(context))->ServiceConnected();
- } else {
- LoggerE("Context is null");
- }
- }
-
- void eventHandler(SEServiceHelper *service, char *se_name, int event, void *context) {
- LoggerD("Entered");
- if (context) {
- (static_cast<SEService*>(context))->EventHandler(se_name, event);
- } else {
- LoggerE("Context is null");
- }
- }
-
- void errorHandler(SEServiceHelper *service, int error, void *context) {
- LoggerE("Error handler called, code: %d", error);
- if (context) {
- (static_cast<SEService*>(context))->ErrorHandler(error);
- } else {
- LoggerE("Context is null");
- }
- }
-};
-
-static SEServiceEventHandler se_event_handler;
-
-SEService::SEService(SecureElementInstance& instance)
- : is_initialized_(false),
- is_listener_set_(false),
- is_error_(false),
- instance_(instance) {
- LoggerD("Entered");
-
- se_service_ = new smartcard_service_api::SEService((void *)this, &se_event_handler);
-}
-
-SEService::~SEService() {
- LoggerD("Entered");
-
- if (is_initialized_) {
- se_service_->shutdownSync();
- is_initialized_ = false;
- }
-
- delete se_service_;
- se_service_ = nullptr;
-}
-
-void SEService::GetReaders(double callback_id) {
- LoggerD("Entered");
-
- auto get_readers = [this](
- const std::shared_ptr<picojson::value>& response) -> void {
- picojson::value result = picojson::value(picojson::array());
- picojson::array& result_array = result.get<picojson::array>();
-
- std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
- for (std::size_t i = 0; i < readers.size(); i++) {
- if (readers[i]->isSecureElementPresent()) {
- result_array.push_back(picojson::value((double) (long) readers[i]));
- }
- }
-
- ReportSuccess(result, response->get<picojson::object>());
- };
-
- auto get_readers_response = [this, callback_id](
- const std::shared_ptr<picojson::value>& response) -> void {
- picojson::object& obj = response->get<picojson::object>();
- obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
- Instance::PostMessage(&instance_, response->serialize().c_str());
- };
-
- if (is_error_) {
- // there has been an error, report it asynchronously
- std::shared_ptr<picojson::value> response{new picojson::value{picojson::object{}}};
- LogAndReportError(
- PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
- "Unable to connect to service."),
- &response->get<picojson::object>(),
- ("Failed: is_error_"));
- TaskQueue::GetInstance().Async<picojson::value>(get_readers_response, response);
- return;
- }
-
- if (!is_initialized_) {
- // not yet ready, wait for the platform callback, send the response then
- get_readers_callbacks_.push_back(callback_id);
- return;
- }
-
- auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
-
- // everything's fine, get the readers, send the response
- TaskQueue::GetInstance().Queue<picojson::value>(
- get_readers,
- get_readers_response,
- data);
-}
-
-void SEService::RegisterSEListener() {
- LoggerD("Entered");
-
- is_listener_set_ = true;
-}
-
-void SEService::UnregisterSEListener() {
- LoggerD("Entered");
-
- is_listener_set_ = false;
-}
-
-void SEService::Shutdown() {
- LoggerD("Entered");
-
- if (is_initialized_) {
- se_service_->shutdownSync();
- is_initialized_ = false;
- }
-}
-
-void SEService::ServiceConnected() {
- LoggerD("Entered");
-
- is_initialized_ = true;
-
- // send the response to pending GetReaders callbacks
- for (const auto& callback_id : get_readers_callbacks_) {
- GetReaders(callback_id);
- }
- get_readers_callbacks_.clear();
-
- // notify the listeners
- if (!is_listener_set_) {
- LoggerE("SE listener is not set.");
- return;
- }
-
- std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
- for (std::size_t i = 0; i < readers.size(); i++) {
- if (readers[i]->isSecureElementPresent()) {
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
-
- obj.insert(std::make_pair("action", picojson::value("onSEReady")));
- obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
-
- Instance::PostMessage(&instance_, result.serialize().c_str());
- }
- }
-}
-
-void SEService::EventHandler(char *se_name, int event) {
- LoggerD("Entered");
-
- if (SE_INSERTED != event && SE_REMOVED != event) {
- LoggerD("Incorrect event type");
- return;
- }
-
- if (is_initialized_ && is_listener_set_) {
- bool is_present = event == SE_INSERTED;
-
- std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
- for (std::size_t i = 0; i < readers.size(); i++) {
- if (!strcmp(se_name, readers[i]->getName()) &&
- readers[i]->isSecureElementPresent() != is_present) {
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
-
- if (is_present) {
- obj.insert(std::make_pair("action", picojson::value("onSEReady")));
- } else {
- obj.insert(std::make_pair("action", picojson::value("onSENotReady")));
- }
-
- obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
- Instance::PostMessage(&instance_, result.serialize().c_str());
- return;
- }
- }
- }
-}
-
-void SEService::ErrorHandler(int error) {
- LoggerD("Entered");
- is_error_ = true;
-
- for (const auto& callback_id : get_readers_callbacks_) {
- GetReaders(callback_id);
- }
- get_readers_callbacks_.clear();
-}
-
-} // secureelement
-} // extension
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SECUREELEMENT_SESERVICE_H_
-#define SECUREELEMENT_SESERVICE_H_
-
-#include <SEService.h>
-#include <SEServiceHelper.h>
-
-namespace extension {
-namespace secureelement {
-
-class SecureElementInstance;
-
-class SEService {
- public:
- explicit SEService(SecureElementInstance& instance);
- ~SEService();
-
- void GetReaders(double callback_id);
- void RegisterSEListener();
- void UnregisterSEListener();
- void Shutdown();
-
- void ServiceConnected();
- void EventHandler(char *se_name, int event);
- void ErrorHandler(int error);
- private:
- SEService(const SEService&) = delete;
- SEService& operator=(const SEService&) = delete;
-
- smartcard_service_api::SEService *se_service_;
- bool is_initialized_;
- bool is_listener_set_;
- bool is_error_;
- std::vector<double> get_readers_callbacks_;
- SecureElementInstance& instance_;
-};
-
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_SESERVICE_H_
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <Session.h>
-#include <ClientChannel.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "secureelement_session.h"
-
-using namespace smartcard_service_api;
-
-namespace extension {
-namespace secureelement {
-
-picojson::value SESession::openBasicChannel(const picojson::array& v_aid) {
- LoggerD("Entered");
-
- size_t v_aid_size = v_aid.size();
- unsigned char* aid = new unsigned char[v_aid_size];
- for (size_t i = 0; i < v_aid_size; i++) {
- aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
- }
- ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
- ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openBasicChannelSync( aid_byte_array));
- delete [] aid;
-
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
- obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
- obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
-
- return result;
-}
-
-
-picojson::value SESession::openLogicalChannel(const picojson::array& v_aid) {
- LoggerD("Entered");
-
- size_t v_aid_size = v_aid.size();
- unsigned char* aid = new unsigned char[v_aid_size];
- for (size_t i = 0; i < v_aid_size; i++) {
- aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
- }
- ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
- ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openLogicalChannelSync( aid_byte_array));
- delete [] aid;
-
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
- obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
- obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
-
- return result;
-}
-
-
-picojson::value SESession::isClosed() {
- LoggerD("Entered");
- bool is_closed = m_session_ptr->isClosed();
- picojson::value result = picojson::value(picojson::object());
- picojson::object& obj = result.get<picojson::object>();
- obj.insert(std::make_pair("isClosed", picojson::value(is_closed)));
- return result;
-}
-
-
-void SESession::close() {
- LoggerD("Entered");
- if ( m_session_ptr) {
- m_session_ptr->closeSync();
- }
-}
-
-
-ByteArray SESession::getATR() {
- LoggerD("Entered");
- ByteArray response;
- if ( m_session_ptr) {
- response = m_session_ptr->getATRSync();
- }
- return response;
-}
-
-
-void SESession::closeChannels() {
- LoggerD("Entered");
- if ( m_session_ptr) {
- m_session_ptr->closeChannels();
- }
-}
-
-
-} // secureelement
-} // extension
+++ /dev/null
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SECUREELEMENT_SESSION_H_
-#define SECUREELEMENT_SESSION_H_
-
-#include <Session.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-
-namespace extension {
-namespace secureelement {
-
-class SESession {
-public:
- SESession(smartcard_service_api::Session* session_ptr)
- : m_session_ptr(session_ptr) {
- }
-
- ~SESession() {};
- picojson::value openBasicChannel( const picojson::array& v_aid);
- picojson::value openLogicalChannel( const picojson::array& v_aid);
- picojson::value isClosed();
- void close();
- smartcard_service_api::ByteArray getATR();
- void closeChannels();
-private:
- smartcard_service_api::Session* m_session_ptr;
-};
-
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_SESSION_H_
],
},
],
+ [
+ 'tizen_feature_convergence_support==1', {
+ 'dependencies': [
+ 'convergence/convergence.gyp:*',
+ ],
+ },
+ ],
], # end conditions
},
], # end targets
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
#include <common/extension.h>
return -1;
}
- DIR * dir;
- struct dirent ent = {0};
- struct dirent* result = nullptr;
- if ((dir = opendir(tec_path.c_str())) != NULL) {
- while ((0 == (readdir_r(dir, &ent, &result))) && result) {
- std::string fname = ent.d_name;
+ struct dirent** namelist;
+ int num_entries = scandir(tec_path.c_str(), &namelist, NULL, alphasort);
+ if( num_entries >= 0 ) {
+ for( int i = 0; i < num_entries; ++i ) {
+ std::string fname = namelist[i]->d_name;
if (fname.size() >= prefix_.size() + postfix_.size() &&
!fname.compare(0, prefix_.size(), prefix_) &&
//
// dlclose(handle);
}
+ free(namelist[i]);
}
- closedir(dir);
-
+ free(namelist);
print_json();
} else {
- std::cerr << "path not exist : " << tec_path << std::endl;
+ perror("scandir");
+ if( errno == ENOENT )
+ std::cerr << "path not exist : " << tec_path << std::endl;
return -1;
}