Binary Exchanging Support
authorWonYoung Choi <wy80.choi@samsung.com>
Sat, 1 Aug 2015 05:52:33 +0000 (14:52 +0900)
committerPawel Kaczmarek <p.kaczmarek3@samsung.com>
Tue, 11 Aug 2015 08:16:36 +0000 (10:16 +0200)
Change-Id: I02f7140bd71961cd171d556a941a36184379f412
Signed-off-by: WonYoung Choi <wy80.choi@samsung.com>
src/common/XW_Extension_Data.h [new file with mode: 0644]
src/common/extension.cc
src/common/extension.h

diff --git a/src/common/XW_Extension_Data.h b/src/common/XW_Extension_Data.h
new file mode 100644 (file)
index 0000000..c1b55de
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// XW_INTERNAL_DATA_INTERFACE: allow extensions to exchange binary chunk data
+// between extension and loader.
+//
+
+#define XW_INTERNAL_DATA_INTERFACE_1 \
+  "XW_InternalDataInterface_1"
+#define XW_INTERNAL_DATA_INTERFACE \
+  XW_INTERNAL_DATA_INTERFACE_1
+
+// Synchronous / Asynchronous data exchanging interface
+typedef void (*XW_HandleDataCallback)(XW_Instance instance,
+                                      const char* message,
+                                      uint8_t* buffer, size_t len);
+
+struct XW_Internal_DataInterface_1 {
+  void (*RegisterSync)(XW_Extension extension,
+                       XW_HandleDataCallback handle_data);
+
+  void (*RegisterAsync)(XW_Extension extension,
+                        XW_HandleDataCallback handle_data);
+
+  void (*SetSyncReply)(XW_Instance instance, const char* reply,
+                       uint8_t* buffer, size_t len);
+
+  void (*PostData)(XW_Instance instance, const char* message,
+                   uint8_t* buffer, size_t len);
+};
+
+typedef struct XW_Internal_DataInterface_1
+    XW_Internal_DataInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
index b033931257a03cefcb6acb6c819d86bd16c9c26b..94ee30899c862c5b98c581c9b309b26f425d058f 100755 (executable)
@@ -33,6 +33,7 @@ const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
 const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
 const XW_Internal_RuntimeInterface* g_runtime = NULL;
 const XW_Internal_PermissionsInterface* g_permission = NULL;
+const XW_Internal_DataInterface* g_data = NULL;
 
 bool InitializeInterfaces(XW_GetInterface get_interface) {
   LoggerD("Enter");
@@ -67,21 +68,28 @@ bool InitializeInterfaces(XW_GetInterface get_interface) {
         get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
     if (!g_entry_points) {
       std::cerr << "NOTE: Entry points interface not available in this version "
-                << "of Crosswalk, ignoring entry point data for extensions.\n";
+                << "of runtime, ignoring entry point data for extensions.\n";
     }
 
     g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
         get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
     if (!g_runtime) {
       std::cerr << "NOTE: runtime interface not available in this version "
-                << "of Crosswalk, ignoring runtime variables for extensions.\n";
+                << "of runtime, ignoring runtime variables for extensions.\n";
     }
 
     g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
         get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
     if (!g_permission) {
       std::cerr << "NOTE: permission interface not available in this version "
-        << "of Crosswalk, ignoring permission for extensions.\n";
+        << "of runtime, ignoring permission for extensions.\n";
+    }
+
+    g_data = reinterpret_cast<const XW_Internal_DataInterface*>(
+        get_interface(XW_INTERNAL_DATA_INTERFACE));
+    if (!g_data) {
+      std::cerr << "NOTE: data interface not available in this version of "
+        << "runtime, ignoring data for extensions.\n";
     }
 
     initialized = true;
@@ -189,6 +197,28 @@ void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) {
   instance->HandleSyncMessage(msg);
 }
 
+// static
+void Extension::HandleData(XW_Instance xw_instance, const char* msg,
+                           uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleData(msg, buffer, len);
+}
+
+// static
+void Extension::HandleSyncData(XW_Instance xw_instance, const char* msg,
+                               uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleSyncData(msg, buffer, len);
+}
+
 //static
 int32_t Extension::XW_Initialize(XW_Extension extension,
                                  XW_GetInterface get_interface,
@@ -216,6 +246,12 @@ int32_t Extension::XW_Initialize(XW_Extension extension,
                                     Extension::OnInstanceDestroyed);
   g_messaging->Register(extension, Extension::HandleMessage);
   g_sync_messaging->Register(extension, Extension::HandleSyncMessage);
+
+  if (g_data) {
+    g_data->RegisterSync(extension, Extension::HandleSyncData);
+    g_data->RegisterAsync(extension, Extension::HandleData);
+  }
+
   return XW_OK;
 }
 
@@ -241,6 +277,18 @@ void Instance::PostMessage(const char* msg) {
   g_messaging->PostMessage(xw_instance_, msg);
 }
 
+
+void Instance::PostData(const char* msg, uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    std::cerr << "Ignoring PostData() in the constructor or after the "
+              << "instance was destroyed.";
+    return;
+  }
+  g_data->PostData(xw_instance_, msg, buffer, len);
+}
+
+
 void Instance::SendSyncReply(const char* reply) {
   LoggerD("Enter");
   if (!xw_instance_) {
@@ -251,6 +299,18 @@ void Instance::SendSyncReply(const char* reply) {
   g_sync_messaging->SetSyncReply(xw_instance_, reply);
 }
 
+void Instance::SendSyncReply(const char* reply, uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    std::cerr << "Ignoring SendSyncReply() in the constructor or after the "
+              << "instance was destroyed.";
+    return;
+  }
+  g_data->SetSyncReply(xw_instance_, reply, buffer, len);
+}
+
+
+// ParsedInstance //////////////////////////////////////////////////////////////
 
 ParsedInstance::ParsedInstance() {
   LoggerD("Enter");
@@ -370,4 +430,124 @@ void ParsedInstance::HandleError(const PlatformResult& e) {
   SendSyncReply(result.serialize().c_str());
 }
 
+// ParsedDataStruct ////////////////////////////////////////////////////////////
+
+ParsedDataStruct::ParsedDataStruct()
+    : buffer_(NULL), buffer_len_(0) {
+}
+
+ParsedDataStruct::ParsedDataStruct(uint8_t* buffer, size_t len)
+    : buffer_(buffer), buffer_len_(len) {
+}
+
+void ParsedDataStruct::SetBuffer(uint8_t* buffer, size_t len) {
+  buffer_ = buffer;
+  buffer_len_ = len;
+}
+
+ParsedDataRequest::ParsedDataRequest(uint8_t* buffer, size_t len)
+    : ParsedDataStruct(buffer, len) {
+}
+
+bool ParsedDataRequest::Parse(const char* msg) {
+  std::string err;
+  picojson::parse(value_, msg, msg + strlen(msg), &err);
+  if (!err.empty()) {
+    std::cerr << "Ignoring message. " << err;
+    return false;
+  }
+
+  if (!value_.is<picojson::object>()) {
+    std::cerr << "Ignoring message. It is not an object.";
+    return false;
+  }
+
+  return true;
+}
+
+std::string ParsedDataRequest::cmd() const {
+  return value_.get("cmd").to_str();
+}
+
+const picojson::value& ParsedDataRequest::args() const {
+  return value_.get("args");
+}
+
+ParsedDataResponse::ParsedDataResponse()
+    : value_(picojson::value(picojson::object())) {
+}
+
+picojson::object& ParsedDataResponse::object() {
+  return value_.get<picojson::object>();
+}
+
+// ParsedDataInstance //////////////////////////////////////////////////////////
+
+void ParsedDataInstance::RegisterHandler(const std::string& name,
+                                         const NativeDataHandler& func) {
+  LoggerD("Enter");
+  data_handler_map_.insert(std::make_pair(name, func));
+}
+
+void ParsedDataInstance::RegisterSyncHandler(const std::string& name,
+                                             const NativeDataHandler& func) {
+  LoggerD("Enter");
+  data_handler_map_.insert(std::make_pair("#SYNC#" + name, func));
+}
+
+void ParsedDataInstance::HandleData(const char* msg,
+                                    uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  HandleData(msg, buffer, len, false);
+}
+
+void ParsedDataInstance::HandleSyncData(const char* msg,
+                                        uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  HandleData(msg, buffer, len, true);
+}
+
+void ParsedDataInstance::HandleData(const char* msg,
+                                    uint8_t* buffer, size_t len, bool is_sync) {
+  LoggerD("Enter");
+  try {
+    ParsedDataRequest request(buffer, len);
+    if (!request.Parse(msg)) {
+      return;
+    }
+
+    // check for args in JSON message
+    const picojson::value& args = request.args();
+    if (!args.is<picojson::object>()) {
+      throw InvalidValuesException("No \"args\" field in message");
+    }
+
+    std::string cmd = (is_sync ? "#SYNC#" : "") + request.cmd();
+    auto it = data_handler_map_.find(cmd);
+    if (data_handler_map_.end() == it) {
+      throw UnknownException("Unknown command.");
+    }
+    NativeDataHandler func = it->second;
+
+    ParsedDataResponse response;
+    func(request, response);
+    if (is_sync) {
+      SendSyncReply(response.value().serialize().c_str(),
+                    response.buffer(), response.buffer_length());
+    }
+  } catch (const PlatformException& e) {
+    return HandleException(e);
+  } catch (const PlatformException* e) {
+    return HandleException(*e);
+  } catch (const std::exception& e) {
+    return HandleException(UnknownException(e.what()));
+  } catch (const std::exception* e) {
+    return HandleException(UnknownException(e->what()));
+  } catch (...) {
+    return HandleException(UnknownException("Unknown exception"));
+  }
+}
+
+
+
 }  // namespace common
index d8c7539179867f2d92dd82af71b5b6e93d35047e..7e67d2b49f8cd3c3bf64897a8e0646682f5b245f 100755 (executable)
@@ -33,6 +33,7 @@
 #include "common/XW_Extension_Permissions.h"
 #include "common/XW_Extension_Runtime.h"
 #include "common/XW_Extension_SyncMessage.h"
+#include "common/XW_Extension_Data.h"
 
 namespace common {
 
@@ -86,6 +87,10 @@ class Extension {
   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 HandleData(XW_Instance xw_instance, const char* msg,
+                         uint8_t* buffer, size_t len);
+  static void HandleSyncData(XW_Instance xw_instance, const char* msg,
+                             uint8_t* buffer, size_t len);
 
   XW_Extension xw_extension_;
 
@@ -98,12 +103,18 @@ class Instance {
   virtual ~Instance();
 
   void PostMessage(const char* msg);
+  void PostData(const char* msg, uint8_t* buffer, size_t len);
   void SendSyncReply(const char* reply);
+  void SendSyncReply(const char* reply, uint8_t* buffer, size_t len);
 
   virtual void Initialize() {}
+
   virtual void HandleMessage(const char* msg) = 0;
   virtual void HandleSyncMessage(const char* msg) {}
 
+  virtual void HandleData(const char* msg, uint8_t* buffer, size_t len) {}
+  virtual void HandleSyncData(const char* msg, uint8_t* buffer, size_t len) {}
+
   XW_Instance xw_instance() const { return xw_instance_; }
 
  private:
@@ -130,17 +141,68 @@ class ParsedInstance : public Instance {
   void ReportError(const PlatformException& ex, picojson::object& out);
   void ReportError(const PlatformResult& error, picojson::object* out);
 
+  void HandleException(const PlatformException& ex);
+  void HandleError(const PlatformResult& error);
+
  private:
   void HandleMessage(const char* msg);
   void HandleSyncMessage(const char* msg);
-
   void HandleMessage(const char* msg, bool is_sync);
-  void HandleException(const PlatformException& ex);
-  void HandleError(const PlatformResult& error);
 
   std::map<std::string, NativeHandler> handler_map_;
 };
 
+class ParsedDataStruct {
+ public:
+  ParsedDataStruct();
+  ParsedDataStruct(uint8_t* buffer, size_t len);
+
+  void SetBuffer(uint8_t* buffer, size_t len);
+
+  uint8_t* buffer() const { return buffer_; }
+  size_t buffer_length() const { return buffer_len_; }
+ private:
+  uint8_t* buffer_;
+  size_t buffer_len_;
+};
+
+class ParsedDataRequest : public ParsedDataStruct {
+ public:
+  ParsedDataRequest(uint8_t* buffer, size_t len);
+
+  bool Parse(const char* msg);
+  std::string cmd() const;
+  const picojson::value& args() const;
+  const picojson::value& value() const { return value_; }
+ private:
+  picojson::value value_;
+};
+
+class ParsedDataResponse : public ParsedDataStruct {
+ public:
+  ParsedDataResponse();
+
+  const picojson::value& value() const { return value_; }
+  picojson::object& object();
+ private:
+  picojson::value value_;
+};
+
+typedef std::function<void(const ParsedDataRequest&, ParsedDataResponse&)>
+    NativeDataHandler;
+
+class ParsedDataInstance : public ParsedInstance {
+ public:
+  void RegisterHandler(const std::string& name, const NativeDataHandler& func);
+  void RegisterSyncHandler(const std::string& name, const NativeDataHandler& func);
+ private:
+  void HandleData(const char* msg, uint8_t* buffer, size_t len);
+  void HandleSyncData(const char* msg, uint8_t* buffer, size_t len);
+  void HandleData(const char* msg, uint8_t* buffer, size_t len, bool is_sync);
+
+  std::map<std::string, NativeDataHandler> data_handler_map_;
+};
+
 }  // namespace common
 
 #endif  // COMMON_EXTENSION_H_