From: Piotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics Date: Fri, 9 Jul 2021 11:47:13 +0000 (+0200) Subject: [extension] Binary messanger implementation added X-Git-Tag: submit/tizen/20210806.090850~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F02%2F261202%2F4;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [extension] Binary messanger implementation added [verification] Code compiles without errors. Change-Id: If98eaf371ffbb47a2bf39978f9529307a9e9b06f --- diff --git a/doc/src/assets/webapi-plugins-devel-test/src/tool/desc_gentool.cc b/doc/src/assets/webapi-plugins-devel-test/src/tool/desc_gentool.cc index b6fda30d..93804f9f 100644 --- a/doc/src/assets/webapi-plugins-devel-test/src/tool/desc_gentool.cc +++ b/doc/src/assets/webapi-plugins-devel-test/src/tool/desc_gentool.cc @@ -105,7 +105,7 @@ const void* get_interface(const char* name) { return &entryPointsInterface1; } - if (!strcmp(name, XW_MESSAGING_INTERFACE_1)) { + if (!strcmp(name, XW_MESSAGING_INTERFACE_2)) { static const XW_MessagingInterface_1 messagingInterface1 = { [](XW_Extension extension, XW_HandleMessageCallback handle_message) { }, diff --git a/src/common/XW_Extension.h b/src/common/XW_Extension.h index 5e6dd9a0..cc89536d 100644 --- a/src/common/XW_Extension.h +++ b/src/common/XW_Extension.h @@ -143,12 +143,14 @@ typedef struct XW_CoreInterface_1 XW_CoreInterface; // code provided by extension. // -#define XW_MESSAGING_INTERFACE_1 "XW_MessagingInterface_1" -#define XW_MESSAGING_INTERFACE XW_MESSAGING_INTERFACE_1 +#define XW_MESSAGING_INTERFACE_2 "XW_MessagingInterface_2" +#define XW_MESSAGING_INTERFACE XW_MESSAGING_INTERFACE_2 typedef void (*XW_HandleMessageCallback)(XW_Instance instance, const char* message); +typedef void (*XW_HandleBinaryMessageCallback)(XW_Instance instance, const char* message, + size_t size); -struct XW_MessagingInterface_1 { +struct XW_MessagingInterface_2 { // Register a callback to be called when the JavaScript code associated // with the extension posts a message. Note that the callback will be called // with the XW_Instance that posted the message as well as the message @@ -162,9 +164,14 @@ struct XW_MessagingInterface_1 { // This function is thread-safe and can be called until the instance is // destroyed. void (*PostMessage)(XW_Instance instance, const char* message); + + // Provides communication for binary data exchange + void (*RegisterBinaryMesssageCallback)(XW_Extension extension, + XW_HandleBinaryMessageCallback handle_message); + void (*PostBinaryMessage)(XW_Instance instance, const char* message, size_t size); }; -typedef struct XW_MessagingInterface_1 XW_MessagingInterface; +typedef struct XW_MessagingInterface_2 XW_MessagingInterface; #ifdef __cplusplus } // extern "C" diff --git a/src/common/extension.cc b/src/common/extension.cc index ca21c41d..94d17a20 100644 --- a/src/common/extension.cc +++ b/src/common/extension.cc @@ -182,6 +182,16 @@ void Extension::HandleMessage(XW_Instance xw_instance, const char* msg) { instance->HandleMessage(msg); } +void Extension::HandleBinaryMessage(XW_Instance xw_instance, const char* msg, size_t size) { + ScopeLogger(); + Instance* instance = reinterpret_cast(g_core->GetInstanceData(xw_instance)); + if (!instance) { + return; + } + // TODO maybe async version will be needed in future + instance->HandleSyncBinaryMessage(msg, size); +} + // static void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) { ScopeLogger(); @@ -215,6 +225,8 @@ int32_t Extension::XW_Initialize(XW_Extension extension, XW_GetInterface get_int g_core->RegisterInstanceCallbacks(extension, created_instance, Extension::OnInstanceDestroyed); g_messaging->Register(extension, Extension::HandleMessage); g_sync_messaging->Register(extension, Extension::HandleSyncMessage); + + g_messaging->RegisterBinaryMesssageCallback(extension, Extension::HandleBinaryMessage); return XW_OK; } @@ -264,6 +276,18 @@ void Instance::PostMessage(Instance* that, const char* msg) { LoggerE("Trying to post message to non-existing instance: [%p], ignoring", that); } +void Instance::PostMessage(Instance* that, const char* msg, size_t size) { + ScopeLogger(); + if (nullptr != that) { + std::lock_guard lock{instances_mutex_}; + if (all_instances_.end() != all_instances_.find(that)) { + that->PostMessage(msg, size); + return; + } + } + LoggerE("Trying to post message to non-existing instance: [%p], ignoring", that); +} + void Instance::PostMessage(Instance* that, const picojson::value& json) { Instance::PostMessage(that, json.serialize().c_str()); } @@ -279,6 +303,17 @@ void Instance::PostMessage(const char* msg) { g_messaging->PostMessage(xw_instance_, msg); } +void Instance::PostMessage(const char* msg, size_t size) { + ScopeLogger(); + if (!xw_instance_) { + LoggerE( + "Ignoring PostMessage() in the constructor or after the " + "instance was destroyed."); + return; + } + g_messaging->PostBinaryMessage(xw_instance_, msg, size); +} + void Instance::SendSyncReply(const char* reply) { ScopeLogger(); if (!xw_instance_) { @@ -308,6 +343,17 @@ void ParsedInstance::RegisterSyncHandler(const std::string& name, const NativeHa handler_map_.insert(std::make_pair("#SYNC#" + name, func)); } +void ParsedInstance::RegisterBinaryHandler(const BinaryNativeHandler& func) { + ScopeLogger(); + binary_handler_vec_.push_back(func); +} + +void ParsedInstance::RegisterBinarySyncHandler(const BinaryNativeHandler& func) { + ScopeLogger(); + // TODO - maybe async version will be needed in future + binary_handler_vec_.push_back(func); +} + void ParsedInstance::ReportSuccess(picojson::object& out) { ScopeLogger(); tools::ReportSuccess(out); @@ -338,11 +384,21 @@ void ParsedInstance::HandleMessage(const char* msg) { HandleMessage(msg, false); } +void ParsedInstance::HandleBinaryMessage(const char* msg, size_t size) { + ScopeLogger(); + HandleBinaryMessage(msg, size, false); +} + void ParsedInstance::HandleSyncMessage(const char* msg) { ScopeLogger(); HandleMessage(msg, true); } +void ParsedInstance::HandleSyncBinaryMessage(const char* msg, size_t size) { + ScopeLogger(); + HandleBinaryMessage(msg, size, true); +} + void ParsedInstance::HandleMessage(const char* msg, bool is_sync) { ScopeLogger(); try { @@ -390,6 +446,29 @@ void ParsedInstance::HandleMessage(const char* msg, bool is_sync) { } } +void ParsedInstance::HandleBinaryMessage(const char* msg, size_t size, bool is_sync) { + ScopeLogger(); + try { + // first byte is a method ID + auto func = binary_handler_vec_.at(msg[0]); + + picojson::value result = picojson::value(picojson::object()); + func(msg + 1, size - 1, result.get()); + + if (is_sync) SendSyncReply(result.serialize().c_str()); + } catch (const std::out_of_range& e) { + return HandleException(UnknownException("Unknown command")); + } catch (const PlatformException& e) { + return HandleException(e); + } catch (const PlatformException* e) { + return HandleException(*e); + } catch (const std::exception& e) { + return HandleException(e); + } catch (...) { + return HandleException(UnknownException("Unknown exception")); + } +} + void ParsedInstance::HandleException(const PlatformException& ex) { ScopeLogger(); LoggerE("Exception: %s", ex.message().c_str()); diff --git a/src/common/extension.h b/src/common/extension.h index 99f459e6..d4594921 100644 --- a/src/common/extension.h +++ b/src/common/extension.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/XW_Extension.h" #include "common/XW_Extension_EntryPoints.h" @@ -82,8 +83,9 @@ class Extension { static void OnInstanceCreated(XW_Instance xw_instance, Instance* instance); // modified static void OnInstanceDestroyed(XW_Instance xw_instance); static void HandleMessage(XW_Instance xw_instance, const char* msg); - static void HandleSyncMessage(XW_Instance xw_instance, const char* msg); + static void HandleSyncMessage(XW_Instance xw_instance, const char* msg); + static void HandleBinaryMessage(XW_Instance instance, const char* message, const size_t size); XW_Extension xw_extension_; class Detail; @@ -97,8 +99,10 @@ class Instance { static void DoAndPostMessage(Instance* that, const std::function& work, const picojson::value& json); static void PostMessage(Instance* that, const char* msg); + static void PostMessage(Instance* that, const char* msg, size_t size); static void PostMessage(Instance* that, const picojson::value& json); void PostMessage(const char* msg); + void PostMessage(const char* msg, size_t size); void SendSyncReply(const char* reply); virtual void Initialize() { @@ -107,6 +111,9 @@ class Instance { virtual void HandleSyncMessage(const char* msg) { } + virtual void HandleBinaryMessage(const char* msg, size_t size) = 0; + virtual void HandleSyncBinaryMessage(const char* msg, size_t size) = 0; + XW_Instance xw_instance() const { return xw_instance_; } @@ -121,6 +128,7 @@ class Instance { }; typedef std::function NativeHandler; +typedef std::function BinaryNativeHandler; class ParsedInstance : public Instance { public: @@ -131,6 +139,9 @@ class ParsedInstance : public Instance { void RegisterHandler(const std::string& name, const NativeHandler& func); void RegisterSyncHandler(const std::string& name, const NativeHandler& func); + void RegisterBinaryHandler(const BinaryNativeHandler& func); + void RegisterBinarySyncHandler(const BinaryNativeHandler& func); + static void ReportSuccess(picojson::object& out); static void ReportSuccess(const picojson::value& result, picojson::object& out); static void ReportError(picojson::object& out); @@ -141,12 +152,17 @@ class ParsedInstance : public Instance { void HandleMessage(const char* msg); void HandleSyncMessage(const char* msg); + void HandleBinaryMessage(const char* msg, size_t size); + void HandleSyncBinaryMessage(const char* msg, size_t size); + void HandleMessage(const char* msg, bool is_sync); + void HandleBinaryMessage(const char* msg, size_t size, bool is_sync); void HandleException(const PlatformException& ex); void HandleException(const std::exception& e); void HandleError(const PlatformResult& error); std::map handler_map_; + std::vector binary_handler_vec_; }; } // namespace common diff --git a/src/tool/desc_gentool.cc b/src/tool/desc_gentool.cc index 7c4185c3..86d31b0d 100644 --- a/src/tool/desc_gentool.cc +++ b/src/tool/desc_gentool.cc @@ -100,10 +100,13 @@ const void* get_interface(const char* name) { return &entryPointsInterface1; } - if (!strcmp(name, XW_MESSAGING_INTERFACE_1)) { - static const XW_MessagingInterface_1 messagingInterface1 = { + if (!strcmp(name, XW_MESSAGING_INTERFACE_2)) { + static const XW_MessagingInterface_2 messagingInterface1 = { [](XW_Extension extension, XW_HandleMessageCallback handle_message) {}, - [](XW_Instance instance, const char* message) {}}; + [](XW_Instance instance, const char* message) {}, + [](XW_Extension extension, + XW_HandleBinaryMessageCallback handle_message) {}, + [](XW_Instance instance, const char* message, size_t size) {}}; return &messagingInterface1; } diff --git a/src/utils/utils_api.js b/src/utils/utils_api.js index 684b0f82..e5dde70c 100644 --- a/src/utils/utils_api.js +++ b/src/utils/utils_api.js @@ -1325,6 +1325,18 @@ NativeManager.prototype.callSync = function(cmd, args) { return JSON_.parse(response); }; +NativeManager.prototype.callSyncBinaryWithJSONAnswer = function(uint8array_data) { + // method id should be coded as first byte, refer to: + // extension.cc - ParsedInstance:: HandleBinaryMessage + + var response = this.extension.internal.sendSyncMessage(uint8array_data); + if (response === undefined) { + /* C++ extension didn't set sync response using Instance::SendSyncReply */ + throw new WebAPIException(WebAPIException.ABORT_ERR, 'Internal error'); + } + return JSON_.parse(response); +}; + NativeManager.prototype.sendRuntimeMessage = function(msg, body) { return this.extension.sendRuntimeMessage(msg, body || ''); };