[extension] Binary messanger implementation added 02/261202/4
authorPiotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Fri, 9 Jul 2021 11:47:13 +0000 (13:47 +0200)
committerPiotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Thu, 5 Aug 2021 12:50:27 +0000 (14:50 +0200)
[verification] Code compiles without errors.

Change-Id: If98eaf371ffbb47a2bf39978f9529307a9e9b06f

doc/src/assets/webapi-plugins-devel-test/src/tool/desc_gentool.cc
src/common/XW_Extension.h
src/common/extension.cc
src/common/extension.h
src/tool/desc_gentool.cc
src/utils/utils_api.js

index b6fda30..93804f9 100644 (file)
@@ -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) {
       },
index 5e6dd9a..cc89536 100644 (file)
@@ -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"
index ca21c41..94d17a2 100644 (file)
@@ -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<Instance*>(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<std::mutex> 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<picojson::object>());
+
+    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());
index 99f459e..d459492 100644 (file)
@@ -25,6 +25,7 @@
 #include <mutex>
 #include <string>
 #include <unordered_set>
+#include <vector>
 
 #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<void()>& 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<void(const picojson::value&, picojson::object&)> NativeHandler;
+typedef std::function<void(const char*, size_t size, picojson::object&)> 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<std::string, NativeHandler> handler_map_;
+  std::vector<BinaryNativeHandler> binary_handler_vec_;
 };
 
 }  // namespace common
index 7c4185c..86d31b0 100644 (file)
@@ -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;
   }
 
index 684b0f8..e5dde70 100644 (file)
@@ -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 || '');
 };