--- /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 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_
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");
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;
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,
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;
}
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_) {
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");
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
#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 {
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_;
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:
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_