From: WonYoung Choi Date: Sat, 1 Aug 2015 05:52:33 +0000 (+0900) Subject: Binary Exchanging Support X-Git-Tag: submit/tizen/20151026.073646^2^2~179^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=04b355d7aa6bba7d79a3bada6deeb20f29b5f93b;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git Binary Exchanging Support Change-Id: I02f7140bd71961cd171d556a941a36184379f412 Signed-off-by: WonYoung Choi --- diff --git a/src/common/XW_Extension_Data.h b/src/common/XW_Extension_Data.h new file mode 100644 index 00000000..c1b55def --- /dev/null +++ b/src/common/XW_Extension_Data.h @@ -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_ diff --git a/src/common/extension.cc b/src/common/extension.cc index b0339312..94ee3089 100755 --- a/src/common/extension.cc +++ b/src/common/extension.cc @@ -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( 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( 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( + 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(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(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()) { + 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(); +} + +// 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()) { + 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 diff --git a/src/common/extension.h b/src/common/extension.h index d8c75391..7e67d2b4 100755 --- a/src/common/extension.h +++ b/src/common/extension.h @@ -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 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 + 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 data_handler_map_; +}; + } // namespace common #endif // COMMON_EXTENSION_H_