From: WonYoung Choi Date: Wed, 11 May 2016 01:50:49 +0000 (+0900) Subject: Change to single process model X-Git-Tag: accepted/tizen/common/20160525.155847^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b692f1f0f369f50dc1e0b97d8fc3772b49170387;p=platform%2Fframework%2Fweb%2Fcrosswalk-tizen.git Change to single process model Chromium-efl supports single process model to reduce memory consumption and improve loading performance. The extension server is running in the browser thread in this model. The extension server and client use the ewk IPC methods to exchange messages each other, but the IPC just exchanges the messages between threads. --- diff --git a/common/common.gyp b/common/common.gyp index f399892..ac3327c 100644 --- a/common/common.gyp +++ b/common/common.gyp @@ -9,10 +9,6 @@ 'sources': [ 'command_line.h', 'command_line.cc', - 'dbus_client.h', - 'dbus_client.cc', - 'dbus_server.h', - 'dbus_server.cc', 'file_utils.h', 'file_utils.cc', 'string_utils.h', @@ -46,7 +42,6 @@ 'capi-appfw-package-manager', 'capi-system-system-settings', 'dlog', - 'gio-2.0', 'uuid', 'libwebappenc', 'manifest-parser', @@ -63,7 +58,6 @@ 'variables': { 'packages': [ 'dlog', - 'gio-2.0', ], }, }, diff --git a/common/dbus_client.cc b/common/dbus_client.cc deleted file mode 100644 index 52caa82..0000000 --- a/common/dbus_client.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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. - */ - -#include "common/dbus_client.h" - -#include "common/file_utils.h" -#include "common/logger.h" - -namespace common { - -namespace { - -void OnSignalReceived(GDBusConnection* /*connection*/, - const gchar* /*sender_name*/, - const gchar* /*object_path*/, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data) { - DBusClient* self = reinterpret_cast(user_data); - auto callback = self->GetSignalCallback(interface_name); - if (callback) { - callback(signal_name, parameters); - } -} - -} // namespace - -DBusClient::DBusClient() - : connection_(NULL), - signal_subscription_id_(0) { -} - -DBusClient::~DBusClient() { - if (connection_) { - g_dbus_connection_signal_unsubscribe(connection_, signal_subscription_id_); - g_dbus_connection_close_sync(connection_, NULL, NULL); - } -} - -bool DBusClient::ConnectByName(const std::string& name) { - std::string address("unix:path="); - address.append(utils::GetUserRuntimeDir()); - address.append("/."); - address.append(name); - return Connect(address); -} - -bool DBusClient::Connect(const std::string& address) { - GError *err = NULL; - connection_ = g_dbus_connection_new_for_address_sync( - address.c_str(), - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - NULL, NULL, &err); - if (!connection_) { - LOGGER(ERROR) << "Failed to connect to bus address " << address - << " : " << err->message; - g_error_free(err); - return false; - } - - signal_subscription_id_ = g_dbus_connection_signal_subscribe( - connection_, NULL, NULL, NULL, NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE, - OnSignalReceived, this, NULL); - - return true; -} - -GVariant* DBusClient::Call(const std::string& iface, - const std::string& method, - GVariant* parameters, - const GVariantType* reply_type) { - if (!connection_) { - return NULL; - } - - GError *err = NULL; - GVariant* reply = NULL; - - if (reply_type) { - reply = g_dbus_connection_call_sync( - connection_, NULL, "/", iface.c_str(), method.c_str(), parameters, - reply_type, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); - if (!reply) { - LOGGER(ERROR) << "Failed to CallSync : " << err->message; - g_error_free(err); - } - } else { - g_dbus_connection_call( - connection_, NULL, "/", iface.c_str(), method.c_str(), parameters, - NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); - } - - return reply; -} - -void DBusClient::SetSignalCallback(const std::string& iface, - SignalCallback func) { - signal_callbacks_[iface] = func; -} - -DBusClient::SignalCallback -DBusClient::GetSignalCallback(const std::string& iface) { - return signal_callbacks_[iface]; -} - -} // namespace common diff --git a/common/dbus_client.h b/common/dbus_client.h deleted file mode 100644 index 0863a5c..0000000 --- a/common/dbus_client.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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_COMMON_DBUS_CLIENT_H_ -#define XWALK_COMMON_DBUS_CLIENT_H_ - -#include -#include - -#include -#include -#include - -namespace common { - -class DBusClient { - public: - typedef std::function SignalCallback; - - DBusClient(); - virtual ~DBusClient(); - - bool Connect(const std::string& address); - bool ConnectByName(const std::string& name); - - GVariant* Call(const std::string& iface, const std::string& method, - GVariant* parameters, const GVariantType* reply_type); - - void SetSignalCallback(const std::string& iface, SignalCallback func); - SignalCallback GetSignalCallback(const std::string& iface); - - private: - GDBusConnection* connection_; - guint signal_subscription_id_; - std::map signal_callbacks_; -}; - -} // namespace common - -#endif // XWALK_COMMON_DBUS_CLIENT_H_ diff --git a/common/dbus_server.cc b/common/dbus_server.cc deleted file mode 100644 index 7e3a711..0000000 --- a/common/dbus_server.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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. - */ - -#include "common/dbus_server.h" - -#include "common/logger.h" -#include "common/file_utils.h" - -namespace common { - -namespace { - -static void OnMethodCall(GDBusConnection* connection, - const gchar* /*sender*/, - const gchar* /*object_path*/, - const gchar* interface_name, - const gchar* method_name, - GVariant* parameters, - GDBusMethodInvocation* invocation, - gpointer user_data) { - DBusServer* self = reinterpret_cast(user_data); - if (!self) { - LOGGER(ERROR) << "DBusServer is NULL."; - return; - } - auto callback = self->GetMethodCallback(interface_name); - if (callback) { - callback(connection, method_name, parameters, invocation); - } -} - -static GVariant* OnGetProperty(GDBusConnection* connection, - const gchar* /*sender*/, - const gchar* /*object_path*/, - const gchar* interface_name, - const gchar* property_name, - GError** /*error*/, - gpointer user_data) { - DBusServer* self = reinterpret_cast(user_data); - if (!self) { - LOGGER(ERROR) << "DBusServer is NULL."; - return NULL; - } - - auto callback = - self->GetPropertyGetter(interface_name); - - GVariant* ret = NULL; - if (callback) { - ret = callback(connection, property_name); - } - - return ret; -} - -static gboolean OnSetProperty(GDBusConnection* connection, - const gchar* /*sender*/, - const gchar* /*object_path*/, - const gchar* interface_name, - const gchar* property_name, - GVariant* value, - GError** /*error*/, - gpointer user_data) { - DBusServer* self = reinterpret_cast(user_data); - if (!self) { - LOGGER(ERROR) << "DBusServer is NULL."; - return FALSE; - } - - auto callback = - self->GetPropertySetter(interface_name); - - gboolean ret = FALSE; - if (callback) { - if (callback(connection, property_name, value)) { - ret = TRUE; - } - } - - return ret; -} - -static const GDBusInterfaceVTable kInterfaceVTable = { - OnMethodCall, - OnGetProperty, - OnSetProperty -}; - -static void OnClosedConnection(GDBusConnection* connection, - gboolean /*remote_peer_vanished*/, - GError* /*error*/, - gpointer user_data) { - DBusServer* self = reinterpret_cast(user_data); - if (self) { - auto callback = self->GetDisconnectedCallback(); - if (callback) { - callback(connection); - } - } - - g_signal_handlers_disconnect_by_func(connection, - (gpointer)OnClosedConnection, - user_data); - g_object_unref(connection); -} - -static gboolean OnClientRequest(GDBusServer* /*dbus_server*/, - GDBusConnection* connection, - gpointer user_data) { - GError* err = NULL; - DBusServer* self = reinterpret_cast(user_data); - - g_signal_connect(connection, "closed", - G_CALLBACK(OnClosedConnection), self); - - if (self) { - // Check Peer Credentials - DBusServer::PeerCredentialsCallback callback = - self->GetPeerCredentialsCallback(); - if (callback && !callback( - g_dbus_connection_get_peer_credentials(connection))) { - LOGGER(WARN) << "Invalid peer credentials."; - g_dbus_connection_close_sync(connection, NULL, NULL); - } - - GDBusNodeInfo* node_info = self->GetIntrospectionNodeInfo(); - if (!node_info) { - LOGGER(ERROR) << "Introspection is not set."; - return TRUE; - } - - // TODO(wy80.choi): register multiple interfaces - g_object_ref(connection); - guint reg_id = g_dbus_connection_register_object( - connection, - "/", - node_info->interfaces[0], - &kInterfaceVTable, - self, - NULL, - &err); - if (reg_id == 0) { - LOGGER(ERROR) << "Failed to register object : " << err->message; - g_error_free(err); - } - } - return TRUE; -} - -} // namespace - -DBusServer::DBusServer() - : server_(NULL), - node_info_(NULL) { -} - -DBusServer::~DBusServer() { - if (node_info_) { - g_dbus_node_info_unref(node_info_); - } - - if (server_) { - g_object_unref(server_); - } - - if (!address_path_.empty()) { - unlink(address_path_.c_str()); - } -} - -void DBusServer::Start(const std::string& name) { - GError* err = NULL; - - address_path_.clear(); - address_path_.append(utils::GetUserRuntimeDir()); - address_path_.append("/."); - address_path_.append(name); - // unlink existing bus address - unlink(address_path_.c_str()); - - std::string address("unix:path="); - address.append(address_path_); - - // create new bus socket - // TODO(wy80.choi): bus socket (Address) should be removed gracefully - // when application is terminated. - gchar* guid = g_dbus_generate_guid(); - server_ = g_dbus_server_new_sync( - address.c_str(), G_DBUS_SERVER_FLAGS_NONE, - guid, NULL, NULL, &err); - g_free(guid); - if (!server_) { - LOGGER(ERROR) << "Failed to create dbus server : " << err->message; - g_error_free(err); - return; - } - - // start server - g_signal_connect(server_, "new-connection", - G_CALLBACK(OnClientRequest), this); - - g_dbus_server_start(server_); -} - -std::string DBusServer::GetClientAddress() const { - return std::string(g_dbus_server_get_client_address(server_)); -} - -void DBusServer::SetIntrospectionXML(const std::string& xml) { - GError* err = NULL; - node_info_ = g_dbus_node_info_new_for_xml(xml.c_str(), &err); - if (!node_info_) { - LOGGER(ERROR) << "Failed to create node info from introspection xml : " - << err->message; - g_error_free(err); - } -} - -void DBusServer::SendSignal(GDBusConnection* connection, - const std::string& iface, - const std::string& signal_name, - GVariant* parameters) { - GError* err = NULL; - gboolean ret = g_dbus_connection_emit_signal( - connection, NULL, "/", - iface.c_str(), signal_name.c_str(), - parameters, &err); - if (!ret) { - LOGGER(ERROR) << "Failed to emit signal : '" - << iface << '.' << signal_name << "'"; - g_error_free(err); - } -} - -void DBusServer::SetDisconnectedCallback(DisconnectedCallback func) { - disconnected_callback_ = func; -} - -void DBusServer::SetPeerCredentialsCallback(PeerCredentialsCallback func) { - peer_credentials_callback_ = func; -} - -void DBusServer::SetMethodCallback( - const std::string& iface, MethodCallback func) { - method_callbacks_[iface] = func; -} - -void DBusServer::SetPropertyGetter( - const std::string& iface, PropertyGetter func) { - property_getters_[iface] = func; -} - -void DBusServer::SetPropertySetter( - const std::string& iface, PropertySetter func) { - property_setters_[iface] = func; -} - -DBusServer::DisconnectedCallback -DBusServer::GetDisconnectedCallback() const { - return disconnected_callback_; -} - -DBusServer::PeerCredentialsCallback -DBusServer::GetPeerCredentialsCallback() const { - return peer_credentials_callback_; -} - -DBusServer::MethodCallback -DBusServer::GetMethodCallback(const std::string& iface) { - return method_callbacks_[iface]; -} - -DBusServer::PropertySetter -DBusServer::GetPropertySetter(const std::string& iface) { - return property_setters_[iface]; -} - -DBusServer::PropertyGetter -DBusServer::GetPropertyGetter(const std::string& iface) { - return property_getters_[iface]; -} - -} // namespace common diff --git a/common/dbus_server.h b/common/dbus_server.h deleted file mode 100644 index 112f891..0000000 --- a/common/dbus_server.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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_COMMON_DBUS_SERVER_H_ -#define XWALK_COMMON_DBUS_SERVER_H_ - -#include -#include -#include -#include -#include - -namespace common { - -class DBusServer { - public: - typedef std::function PeerCredentialsCallback; - typedef std::function MethodCallback; - typedef std::function PropertyGetter; - typedef std::function PropertySetter; - typedef std::function DisconnectedCallback; - - DBusServer(); - virtual ~DBusServer(); - - void Start(const std::string& name); - - std::string GetClientAddress() const; - - void SetIntrospectionXML(const std::string& xml); - GDBusNodeInfo* GetIntrospectionNodeInfo() const { return node_info_; } - - void SendSignal(GDBusConnection* connection, - const std::string& iface, const std::string& signal_name, - GVariant* parameters); - - void SetDisconnectedCallback(DisconnectedCallback func); - void SetPeerCredentialsCallback(PeerCredentialsCallback func); - void SetMethodCallback(const std::string& iface, MethodCallback func); - void SetPropertyGetter(const std::string& iface, PropertyGetter func); - void SetPropertySetter(const std::string& iface, PropertySetter func); - DisconnectedCallback GetDisconnectedCallback() const; - PeerCredentialsCallback GetPeerCredentialsCallback() const; - MethodCallback GetMethodCallback(const std::string& iface); - PropertySetter GetPropertySetter(const std::string& iface); - PropertyGetter GetPropertyGetter(const std::string& iface); - - private: - std::string address_path_; - GDBusServer* server_; - GDBusNodeInfo* node_info_; - - DisconnectedCallback disconnected_callback_; - PeerCredentialsCallback peer_credentials_callback_; - std::map method_callbacks_; - std::map property_getters_; - std::map property_setters_; -}; - -} // namespace common - -#endif // XWALK_COMMON_DBUS_SERVER_H_ diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc index 69ef48f..cfc9fa4 100644 --- a/extensions/common/constants.cc +++ b/extensions/common/constants.cc @@ -18,14 +18,13 @@ namespace extensions { -const char kDBusNameForExtension[] = "Extension"; -const char kDBusInterfaceNameForExtension[] = "org.tizen.xwalk.Extension"; -const char kMethodGetExtensions[] = "GetExtensions"; -const char kMethodCreateInstance[] = "CreateInstance"; -const char kMethodDestroyInstance[] = "DestroyInstance"; -const char kMethodSendSyncMessage[] = "SendSyncMessage"; -const char kMethodPostMessage[] = "PostMessage"; -const char kSignalOnMessageToJS[] = "OnMessageToJS"; -const char kMethodGetJavascriptCode[] = "GetJavascriptCode"; +const char kMethodGetExtensions[] = "xwalk://GetExtensions"; +const char kMethodCreateInstance[] = "xwalk://CreateInstance"; +const char kMethodDestroyInstance[] = "xwalk://DestroyInstance"; +const char kMethodSendSyncMessage[] = "xwalk://SendSyncMessage"; +const char kMethodPostMessage[] = "xwalk://PostMessage"; +const char kMethodGetAPIScript[] = "xwalk://GetAPIScript"; +const char kMethodPostMessageToJS[] = "xwalk://PostMessageToJS"; + } // namespace extensions diff --git a/extensions/common/constants.h b/extensions/common/constants.h index 6d0eb5d..588f09b 100644 --- a/extensions/common/constants.h +++ b/extensions/common/constants.h @@ -19,15 +19,13 @@ namespace extensions { -extern const char kDBusNameForExtension[]; -extern const char kDBusInterfaceNameForExtension[]; extern const char kMethodGetExtensions[]; extern const char kMethodCreateInstance[]; extern const char kMethodDestroyInstance[]; extern const char kMethodSendSyncMessage[]; extern const char kMethodPostMessage[]; -extern const char kSignalOnMessageToJS[]; -extern const char kMethodGetJavascriptCode[]; +extern const char kMethodGetAPIScript[]; +extern const char kMethodPostMessageToJS[]; } // namespace extensions diff --git a/extensions/common/xwalk_extension_manager.cc b/extensions/common/xwalk_extension_manager.cc index 87817d2..1d3e50d 100644 --- a/extensions/common/xwalk_extension_manager.cc +++ b/extensions/common/xwalk_extension_manager.cc @@ -5,6 +5,7 @@ #include "extensions/common/xwalk_extension_manager.h" #include +#include #include #include @@ -20,6 +21,10 @@ #include "extensions/common/constants.h" #include "extensions/common/xwalk_extension.h" +#ifndef EXTENSION_PATH + #error EXTENSION_PATH is not set. +#endif + namespace extensions { namespace { @@ -30,6 +35,14 @@ const char kExtensionPrefix[] = "lib"; const char kExtensionSuffix[] = ".so"; const char kExtensionMetadataSuffix[] = ".json"; +static const char* kPreloadLibs[] = { + EXTENSION_PATH"/libtizen.so", + EXTENSION_PATH"/libtizen_common.so", + EXTENSION_PATH"/libtizen_application.so", + EXTENSION_PATH"/libtizen_utils.so", + NULL +}; + } // namespace XWalkExtensionManager::XWalkExtensionManager() { @@ -38,16 +51,23 @@ XWalkExtensionManager::XWalkExtensionManager() { XWalkExtensionManager::~XWalkExtensionManager() { } +void XWalkExtensionManager::PreloadExtensions() { + for (int i = 0; kPreloadLibs[i]; i++) { + LOGGER(DEBUG) << "Preload libs : " << kPreloadLibs[i]; + void* handle = dlopen(kPreloadLibs[i], RTLD_NOW|RTLD_GLOBAL); + if (handle == nullptr) { + LOGGER(WARN) << "Fail to load libs : " << dlerror(); + } + } +} + void XWalkExtensionManager::LoadExtensions(bool meta_only) { if (!extensions_.empty()) { return; } -#ifdef EXTENSION_PATH std::string extension_path(EXTENSION_PATH); -#else - #error EXTENSION_PATH is not set. -#endif + // Gets all extension files in the EXTENSION_PATH std::string ext_pattern(extension_path); ext_pattern.append("/"); @@ -131,11 +151,7 @@ void XWalkExtensionManager::RegisterExtension(XWalkExtension* extension) { void XWalkExtensionManager::RegisterExtensionsByMeta( const std::string& meta_path, StringSet* files) { -#ifdef EXTENSION_PATH std::string extension_path(EXTENSION_PATH); -#else - #error EXTENSION_PATH is not set. -#endif std::ifstream metafile(meta_path.c_str()); if (!metafile.is_open()) { diff --git a/extensions/common/xwalk_extension_manager.h b/extensions/common/xwalk_extension_manager.h index 8a0cd78..71c6575 100644 --- a/extensions/common/xwalk_extension_manager.h +++ b/extensions/common/xwalk_extension_manager.h @@ -19,11 +19,13 @@ class XWalkExtensionManager : public XWalkExtension::XWalkExtensionDelegate { typedef std::map ExtensionMap; XWalkExtensionManager(); - ~XWalkExtensionManager(); + virtual ~XWalkExtensionManager(); ExtensionMap extensions() const { return extensions_; } void LoadExtensions(bool meta_only = true); + void PreloadExtensions(); + private: // override void GetRuntimeVariable(const char* key, char* value, size_t value_len); diff --git a/extensions/common/xwalk_extension_server.cc b/extensions/common/xwalk_extension_server.cc new file mode 100644 index 0000000..5009af1 --- /dev/null +++ b/extensions/common/xwalk_extension_server.cc @@ -0,0 +1,217 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension_server.h" + +#include + +#include + +#include "common/logger.h" +#include "common/profiler.h" +#include "common/string_utils.h" +#include "extensions/common/constants.h" +#include "extensions/common/xwalk_extension_manager.h" + +namespace extensions { + +// static +XWalkExtensionServer* XWalkExtensionServer::GetInstance() { + static XWalkExtensionServer self; + return &self; +} + +XWalkExtensionServer::XWalkExtensionServer() { + manager_.LoadExtensions(); +} + +XWalkExtensionServer::~XWalkExtensionServer() { +} + +void XWalkExtensionServer::SetupIPC(Ewk_Context* ewk_context) { + ewk_context_ = ewk_context; +} + +void XWalkExtensionServer::Preload() { + manager_.PreloadExtensions(); +} + +Json::Value XWalkExtensionServer::GetExtensions() { + Json::Value out; + auto extensions = manager_.extensions(); + for (auto it = extensions.begin(); it != extensions.end(); ++it) { + Json::Value ext; + ext["name"] = it->second->name(); + // ext["api"] = it->second->GetJavascriptCode(); + auto entry_points = it->second->entry_points(); + for (auto ite = entry_points.begin(); ite != entry_points.end(); ++ite) { + ext["entry_points"].append(*ite); + } + out.append(ext); + } + return out; +} + +std::string XWalkExtensionServer::GetAPIScript( + const std::string& extension_name) { + auto extensions = manager_.extensions(); + auto it = extensions.find(extension_name); + if (it == extensions.end()) { + LOGGER(ERROR) << "No such extension '" << extension_name << "'"; + return std::string(); + } + + return it->second->GetJavascriptCode(); +} + +std::string XWalkExtensionServer::CreateInstance( + const std::string& extension_name) { + std::string instance_id; + + auto extensions = manager_.extensions(); + auto it = extensions.find(extension_name); + if (it != extensions.end()) { + XWalkExtensionInstance* instance = it->second->CreateInstance(); + if (instance) { + instance_id = common::utils::GenerateUUID(); + instance->SetPostMessageCallback( + [this, instance_id](const std::string& msg) { + Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(ans, kMethodPostMessageToJS); + ewk_ipc_wrt_message_data_id_set(ans, instance_id.c_str()); + ewk_ipc_wrt_message_data_value_set(ans, msg.c_str()); + if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { + LOGGER(ERROR) << "Failed to send response"; + } + ewk_ipc_wrt_message_data_del(ans); + }); + + instances_[instance_id] = instance; + } else { + LOGGER(ERROR) << "Failed to create instance of the extension '" + << extension_name << "'"; + } + } else { + LOGGER(ERROR) << "No such extension '" << extension_name << "'"; + } + return instance_id; +} + +void XWalkExtensionServer::HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data) { + if (!data) { + LOGGER(ERROR) << "Invalid parameter. data is NULL."; + return; + } + + if (!ewk_context_) { + LOGGER(WARN) << "IPC is not ready yet."; + return; + } + + Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(data); + #define TYPE_IS(x) (!strcmp(msg_type, x)) + + if (TYPE_IS(kMethodGetExtensions)) { + HandleGetExtensions(data); + } else if (TYPE_IS(kMethodCreateInstance)) { + HandleCreateInstance(data); + } else if (TYPE_IS(kMethodDestroyInstance)) { + HandleDestroyInstance(data); + } else if (TYPE_IS(kMethodPostMessage)) { + HandlePostMessageToNative(data); + } else if (TYPE_IS(kMethodSendSyncMessage)) { + HandleSendSyncMessageToNative(data); + } else if (TYPE_IS(kMethodGetAPIScript)) { + HandleGetAPIScript(data); + } + + eina_stringshare_del(msg_type); + #undef TYPE_IS +} + +void XWalkExtensionServer::HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data) { + Json::Value reply = GetExtensions(); + Json::FastWriter writer; + std::string reply_str = writer.write(reply); + ewk_ipc_wrt_message_data_value_set(data, reply_str.c_str()); +} + +void XWalkExtensionServer::HandleCreateInstance( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + + std::string instance_id = CreateInstance(extension_name); + + ewk_ipc_wrt_message_data_value_set(data, instance_id.c_str()); + + eina_stringshare_del(extension_name); +} + +void XWalkExtensionServer::HandleDestroyInstance( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + XWalkExtensionInstance* instance = it->second; + delete instance; + instances_.erase(it); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandlePostMessageToNative( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + XWalkExtensionInstance* instance = it->second; + instance->HandleMessage(msg); + eina_stringshare_del(msg); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandleSendSyncMessageToNative( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + XWalkExtensionInstance* instance = it->second; + std::string reply; + instance->SetSendSyncReplyCallback([&reply](const std::string& msg) { + reply = msg; + }); + instance->HandleSyncMessage(msg); + ewk_ipc_wrt_message_data_value_set(data, reply.c_str()); + eina_stringshare_del(msg); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandleGetAPIScript( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + + std::string api = GetAPIScript(extension_name); + + ewk_ipc_wrt_message_data_value_set(data, api.c_str()); + + eina_stringshare_del(extension_name); +} + +} // namespace extensions diff --git a/extensions/common/xwalk_extension_server.h b/extensions/common/xwalk_extension_server.h new file mode 100644 index 0000000..fd6cce1 --- /dev/null +++ b/extensions/common/xwalk_extension_server.h @@ -0,0 +1,53 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ + +#include +#include + +#include +#include + +#include "extensions/common/xwalk_extension_manager.h" +#include "extensions/common/xwalk_extension_instance.h" + +namespace extensions { + +class XWalkExtensionServer { + public: + static XWalkExtensionServer* GetInstance(); + + void SetupIPC(Ewk_Context* ewk_context); + void Preload(); + Json::Value GetExtensions(); + std::string GetAPIScript(const std::string& extension_name); + std::string CreateInstance(const std::string& extension_name); + + void HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data); + + private: + XWalkExtensionServer(); + virtual ~XWalkExtensionServer(); + + void HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data); + void HandleCreateInstance(Ewk_IPC_Wrt_Message_Data* data); + void HandleDestroyInstance(Ewk_IPC_Wrt_Message_Data* data); + void HandlePostMessageToNative(Ewk_IPC_Wrt_Message_Data* data); + void HandleSendSyncMessageToNative(Ewk_IPC_Wrt_Message_Data* data); + void HandleGetAPIScript(Ewk_IPC_Wrt_Message_Data* data); + + typedef std::map InstanceMap; + + Ewk_Context* ewk_context_; + + XWalkExtensionManager manager_; + + InstanceMap instances_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 0f95748..c7eb0c6 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -4,8 +4,8 @@ ], 'targets': [ { - 'target_name': 'xwalk_extension_renderer', - 'type': 'static_library', + 'target_name': 'xwalk_extension_shared', + 'type': 'shared_library', 'dependencies': [ '../common/common.gyp:xwalk_tizen_common', ], @@ -20,6 +20,8 @@ 'common/xwalk_extension_adapter.cc', 'common/xwalk_extension_manager.h', 'common/xwalk_extension_manager.cc', + 'common/xwalk_extension_server.h', + 'common/xwalk_extension_server.cc', 'renderer/xwalk_extension_client.h', 'renderer/xwalk_extension_client.cc', 'renderer/xwalk_extension_module.h', @@ -37,13 +39,26 @@ 'renderer/runtime_ipc_client.h', 'renderer/runtime_ipc_client.cc', ], + 'cflags': [ + '-fvisibility=default', + ], 'variables': { 'packages': [ 'chromium-efl', 'elementary', ], }, - }, # end of target 'xwalk_extension_renderer' + 'direct_dependent_settings': { + 'libraries': [ + '-lxwalk_extension_shared', + ], + 'variables': { + 'packages': [ + 'jsoncpp', + ], + }, + }, + }, # end of target 'xwalk_extension_static' { 'target_name': 'widget_plugin', 'type': 'shared_library', diff --git a/extensions/renderer/runtime_ipc_client.cc b/extensions/renderer/runtime_ipc_client.cc index aaae627..d612ae0 100644 --- a/extensions/renderer/runtime_ipc_client.cc +++ b/extensions/renderer/runtime_ipc_client.cc @@ -17,6 +17,7 @@ #include "extensions/renderer/runtime_ipc_client.h" #include "common/logger.h" +#include "common/profiler.h" #include "common/string_utils.h" namespace extensions { @@ -77,16 +78,35 @@ void RuntimeIPCClient::SetRoutingId(v8::Handle context, void RuntimeIPCClient::SendMessage(v8::Handle context, const std::string& type, const std::string& value) { + SendMessage(context, type, "", "", value); +} + +void RuntimeIPCClient::SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value) { + SendMessage(context, type, id, "", value); +} + +void RuntimeIPCClient::SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value) { + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return; + } + Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_id_set(msg, ""); ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); + ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); + ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - int routing_id = GetRoutingId(context); - if (routing_id > 0) { - if (!ewk_ipc_plugins_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - } + if (!ewk_ipc_plugins_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; } ewk_ipc_wrt_message_data_del(msg); @@ -95,23 +115,43 @@ void RuntimeIPCClient::SendMessage(v8::Handle context, std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, const std::string& type, const std::string& value) { + return SendSyncMessage(context, type, "", "", value); +} + +std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value) { + return SendSyncMessage(context, type, id, "", value); +} + +std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value) { + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return std::string(); + } + Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); + ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); + ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - int routing_id = GetRoutingId(context); - if (routing_id > 0) { - if (!ewk_ipc_plugins_sync_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - ewk_ipc_wrt_message_data_del(msg); - return std::string(); - } + if (!ewk_ipc_plugins_sync_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; + ewk_ipc_wrt_message_data_del(msg); + return std::string(); } Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); - std::string result(msg_value); eina_stringshare_del(msg_value); + ewk_ipc_wrt_message_data_del(msg); return result; @@ -121,6 +161,12 @@ void RuntimeIPCClient::SendAsyncMessage(v8::Handle context, const std::string& type, const std::string& value, ReplyCallback callback) { + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return; + } + std::string msg_id = common::utils::GenerateUUID(); Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); @@ -128,13 +174,10 @@ void RuntimeIPCClient::SendAsyncMessage(v8::Handle context, ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - int routing_id = GetRoutingId(context); - if (routing_id > 0) { - if (!ewk_ipc_plugins_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - ewk_ipc_wrt_message_data_del(msg); - return; - } + if (!ewk_ipc_plugins_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; + ewk_ipc_wrt_message_data_del(msg); + return; } callbacks_[msg_id] = callback; diff --git a/extensions/renderer/runtime_ipc_client.h b/extensions/renderer/runtime_ipc_client.h index b5da104..21e1d39 100755 --- a/extensions/renderer/runtime_ipc_client.h +++ b/extensions/renderer/runtime_ipc_client.h @@ -46,13 +46,36 @@ class RuntimeIPCClient { // Send message to BrowserProcess without reply void SendMessage(v8::Handle context, - const std::string& type, const std::string& value); + const std::string& type, + const std::string& value); + + void SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value); + + void SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value); // Send message to BrowserProcess synchronous with reply std::string SendSyncMessage(v8::Handle context, const std::string& type, const std::string& value); + std::string SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value); + + std::string SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value); + // Send message to BrowserProcess asynchronous, // reply message will be passed to callback function. void SendAsyncMessage(v8::Handle context, diff --git a/extensions/renderer/xwalk_extension_client.cc b/extensions/renderer/xwalk_extension_client.cc index 8423d03..d38ec04 100644 --- a/extensions/renderer/xwalk_extension_client.cc +++ b/extensions/renderer/xwalk_extension_client.cc @@ -5,9 +5,10 @@ #include "extensions/renderer/xwalk_extension_client.h" -#include -#include +#include #include +#include +#include #include @@ -15,114 +16,110 @@ #include "common/profiler.h" #include "common/string_utils.h" #include "extensions/common/constants.h" +#include "extensions/common/xwalk_extension_server.h" +#include "extensions/renderer/runtime_ipc_client.h" namespace extensions { +namespace { + void* CreateInstanceInMainloop(void* data) { + const char* extension_name = static_cast(data); + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + std::string instance_id = server->CreateInstance(extension_name); + return static_cast(new std::string(instance_id)); + } +} // namespace + XWalkExtensionClient::XWalkExtensionClient() { } XWalkExtensionClient::~XWalkExtensionClient() { + for (auto it = extension_apis_.begin(); it != extension_apis_.end(); ++it) { + delete it->second; + } + extension_apis_.clear(); } void XWalkExtensionClient::Initialize() { - manager_.LoadExtensions(); -} - -XWalkExtension* XWalkExtensionClient::GetExtension( - const std::string& extension_name) { - // find extension with given the extension name - ExtensionMap extensions = manager_.extensions(); - auto it = extensions.find(extension_name); - if (it == extensions.end()) { - LOGGER(ERROR) << "No such extension '" << extension_name << "'"; - return nullptr; + if (!extension_apis_.empty()) { + return; } - return it->second; -} - -XWalkExtensionClient::ExtensionMap XWalkExtensionClient::GetExtensions() { - return manager_.extensions(); + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + Json::Value reply = server->GetExtensions(); + for (auto it = reply.begin(); it != reply.end(); ++it) { + ExtensionCodePoints* codepoint = new ExtensionCodePoints; + Json::Value entry_points = (*it)["entry_points"]; + for (auto ep = entry_points.begin(); ep != entry_points.end(); ++ep) { + codepoint->entry_points.push_back((*ep).asString()); + } + std::string name = (*it)["name"].asString(); + extension_apis_[name] = codepoint; + } } std::string XWalkExtensionClient::CreateInstance( + v8::Handle context, const std::string& extension_name, InstanceHandler* handler) { - std::string instance_id = common::utils::GenerateUUID(); - - // find extension with given the extension name - ExtensionMap extensions = manager_.extensions(); - auto it = extensions.find(extension_name); - if (it == extensions.end()) { - LOGGER(ERROR) << "No such extension '" << extension_name << "'"; - return std::string(); - } - - // create instance - XWalkExtensionInstance* instance = it->second->CreateInstance(); - if (!instance) { - LOGGER(ERROR) << "Failed to create instance of extension '" - << extension_name << "'"; - return std::string(); - } - - // set callbacks - using std::placeholders::_1; - instance->SetPostMessageCallback([handler](const std::string& msg) { - if (handler) { - handler->HandleMessageFromNative(msg); - } - }); - - instances_[instance_id] = instance; + void* ret = ecore_main_loop_thread_safe_call_sync( + CreateInstanceInMainloop, + static_cast(const_cast(extension_name.data()))); + std::string* sp = static_cast(ret); + std::string instance_id = *sp; + delete sp; + + handlers_[instance_id] = handler; return instance_id; } -void XWalkExtensionClient::DestroyInstance(const std::string& instance_id) { - // find instance with the given instance id - auto it = instances_.find(instance_id); - if (it == instances_.end()) { - LOGGER(ERROR) << "No such instance '" << instance_id << "'"; +void XWalkExtensionClient::DestroyInstance( + v8::Handle context, const std::string& instance_id) { + auto it = handlers_.find(instance_id); + if (it == handlers_.end()) { + LOGGER(WARN) << "Failed to destory invalid instance id: " << instance_id; return; } + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->SendMessage(context, kMethodDestroyInstance, instance_id, ""); - // destroy the instance - XWalkExtensionInstance* instance = it->second; - delete instance; - - instances_.erase(it); + handlers_.erase(it); } void XWalkExtensionClient::PostMessageToNative( + v8::Handle context, const std::string& instance_id, const std::string& msg) { - // find instance with the given instance id - auto it = instances_.find(instance_id); - if (it == instances_.end()) { - LOGGER(ERROR) << "No such instance '" << instance_id << "'"; - return; - } - - // Post a message - XWalkExtensionInstance* instance = it->second; - instance->HandleMessage(msg); + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->SendMessage(context, kMethodPostMessage, instance_id, msg); } std::string XWalkExtensionClient::SendSyncMessageToNative( + v8::Handle context, + const std::string& instance_id, const std::string& msg) { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + std::string reply = + ipc->SendSyncMessage(context, kMethodSendSyncMessage, instance_id, msg); + return reply; +} + +std::string XWalkExtensionClient::GetAPIScript( + v8::Handle context, + const std::string& extension_name) { + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + return server->GetAPIScript(extension_name); +} + +void XWalkExtensionClient::OnReceivedIPCMessage( const std::string& instance_id, const std::string& msg) { - // find instance with the given instance id - auto it = instances_.find(instance_id); - if (it == instances_.end()) { - LOGGER(ERROR) << "No such instance '" << instance_id << "'"; - return std::string(); + auto it = handlers_.find(instance_id); + if (it == handlers_.end()) { + LOGGER(WARN) << "Failed to post the message. Invalid instance id."; + return; } - // Post a message and receive a reply message - std::string reply; - XWalkExtensionInstance* instance = it->second; - instance->SetSendSyncReplyCallback([&reply](const std::string& msg) { - reply = msg; - }); - instance->HandleSyncMessage(msg); - return reply; + if (!it->second) + return; + + it->second->HandleMessageFromNative(msg); } } // namespace extensions diff --git a/extensions/renderer/xwalk_extension_client.h b/extensions/renderer/xwalk_extension_client.h index 9d46444..275be52 100644 --- a/extensions/renderer/xwalk_extension_client.h +++ b/extensions/renderer/xwalk_extension_client.h @@ -6,22 +6,19 @@ #ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_ #define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_ +#include + #include #include #include #include -#include "extensions/common/xwalk_extension.h" -#include "extensions/common/xwalk_extension_instance.h" -#include "extensions/common/xwalk_extension_manager.h" +#include "extensions/renderer/xwalk_module_system.h" namespace extensions { class XWalkExtensionClient { public: - typedef std::map ExtensionMap; - typedef std::map InstanceMap; - struct InstanceHandler { virtual void HandleMessageFromNative(const std::string& msg) = 0; protected: @@ -33,21 +30,39 @@ class XWalkExtensionClient { void Initialize(); - XWalkExtension* GetExtension(const std::string& extension_name); - ExtensionMap GetExtensions(); - - std::string CreateInstance(const std::string& extension_name, + std::string CreateInstance(v8::Handle context, + const std::string& extension_name, InstanceHandler* handler); - void DestroyInstance(const std::string& instance_id); + void DestroyInstance(v8::Handle context, + const std::string& instance_id); - void PostMessageToNative(const std::string& instance_id, + void PostMessageToNative(v8::Handle context, + const std::string& instance_id, const std::string& msg); - std::string SendSyncMessageToNative(const std::string& instance_id, + std::string SendSyncMessageToNative(v8::Handle context, + const std::string& instance_id, const std::string& msg); + std::string GetAPIScript(v8::Handle context, + const std::string& extension_name); + + void OnReceivedIPCMessage(const std::string& instance_id, + const std::string& msg); + + struct ExtensionCodePoints { + std::string api; + std::vector entry_points; + }; + + typedef std::map ExtensionAPIMap; + + const ExtensionAPIMap& extension_apis() const { return extension_apis_; } + private: - XWalkExtensionManager manager_; - InstanceMap instances_; + ExtensionAPIMap extension_apis_; + + typedef std::map HandlerMap; + HandlerMap handlers_; }; } // namespace extensions diff --git a/extensions/renderer/xwalk_extension_module.cc b/extensions/renderer/xwalk_extension_module.cc index 232fb7d..4294ec6 100644 --- a/extensions/renderer/xwalk_extension_module.cc +++ b/extensions/renderer/xwalk_extension_module.cc @@ -13,6 +13,7 @@ #include #include "common/logger.h" +#include "common/profiler.h" #include "extensions/renderer/runtime_ipc_client.h" #include "extensions/renderer/xwalk_extension_client.h" #include "extensions/renderer/xwalk_module_system.h" @@ -48,10 +49,12 @@ const char* kXWalkExtensionModule = "kXWalkExtensionModule"; XWalkExtensionModule::XWalkExtensionModule(XWalkExtensionClient* client, XWalkModuleSystem* module_system, - const std::string& extension_name) : - extension_name_(extension_name), - client_(client), - module_system_(module_system) { + const std::string& extension_name, + const std::string& extension_code) + : extension_name_(extension_name), + extension_code_(extension_code), + client_(client), + module_system_(module_system) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); v8::Handle function_data = v8::Object::New(isolate); @@ -108,7 +111,7 @@ XWalkExtensionModule::~XWalkExtensionModule() { message_listener_.Reset(); if (!instance_id_.empty()) - client_->DestroyInstance(instance_id_); + client_->DestroyInstance(module_system_->GetV8Context(), instance_id_); } namespace { @@ -267,21 +270,21 @@ v8::Handle RunString(const std::string& code, void XWalkExtensionModule::LoadExtensionCode( v8::Handle context, v8::Handle require_native) { - instance_id_ = client_->CreateInstance(extension_name_, this); + instance_id_ = client_->CreateInstance(context, extension_name_, this); if (instance_id_.empty()) { LOGGER(ERROR) << "Failed to create an instance of " << extension_name_; return; } - - - XWalkExtension* ext = client_->GetExtension(extension_name_); - if (ext == nullptr) { - LOGGER(ERROR) << "Failed to get an extension " << extension_name_; - return; + if (extension_code_.empty()) { + extension_code_ = client_->GetAPIScript(context, extension_name_); + if (extension_code_.empty()) { + LOGGER(ERROR) << "Failed to get API script of " << extension_name_; + return; + } } - std::string wrapped_api_code = - WrapAPICode(ext->GetJavascriptCode(), extension_name_); + + std::string wrapped_api_code = WrapAPICode(extension_code_, extension_name_); std::string exception; v8::Handle result = RunString(wrapped_api_code, &exception); @@ -347,7 +350,8 @@ void XWalkExtensionModule::PostMessageCallback( v8::String::Utf8Value value(info[0]->ToString()); // CHECK(module->instance_id_); - module->client_->PostMessageToNative(module->instance_id_, + module->client_->PostMessageToNative(module->module_system_->GetV8Context(), + module->instance_id_, std::string(*value)); result.Set(true); } @@ -366,8 +370,10 @@ void XWalkExtensionModule::SendSyncMessageCallback( // CHECK(module->instance_id_); std::string reply = - module->client_->SendSyncMessageToNative(module->instance_id_, - std::string(*value)); + module->client_->SendSyncMessageToNative( + module->module_system_->GetV8Context(), + module->instance_id_, + std::string(*value)); // If we tried to send a message to an instance that became invalid, // then reply will be NULL. diff --git a/extensions/renderer/xwalk_extension_module.h b/extensions/renderer/xwalk_extension_module.h index eea3d01..1076f0f 100644 --- a/extensions/renderer/xwalk_extension_module.h +++ b/extensions/renderer/xwalk_extension_module.h @@ -28,7 +28,8 @@ class XWalkExtensionModule : public XWalkExtensionClient::InstanceHandler { public: XWalkExtensionModule(XWalkExtensionClient* client, XWalkModuleSystem* module_system, - const std::string& extension_name); + const std::string& extension_name, + const std::string& extension_code); virtual ~XWalkExtensionModule(); // TODO(cmarcelo): Make this return a v8::Handle, and @@ -71,6 +72,7 @@ class XWalkExtensionModule : public XWalkExtensionClient::InstanceHandler { v8::Persistent message_listener_; std::string extension_name_; + std::string extension_code_; XWalkExtensionClient* client_; XWalkModuleSystem* module_system_; diff --git a/extensions/renderer/xwalk_extension_renderer_controller.cc b/extensions/renderer/xwalk_extension_renderer_controller.cc index 6e570aa..384abbb 100644 --- a/extensions/renderer/xwalk_extension_renderer_controller.cc +++ b/extensions/renderer/xwalk_extension_renderer_controller.cc @@ -5,6 +5,7 @@ #include "extensions/renderer/xwalk_extension_renderer_controller.h" +#include #include #include #include @@ -17,6 +18,7 @@ #include "extensions/renderer/xwalk_extension_module.h" #include "extensions/renderer/xwalk_module_system.h" #include "extensions/renderer/xwalk_v8tools_module.h" +#include "extensions/renderer/runtime_ipc_client.h" namespace extensions { @@ -24,14 +26,16 @@ namespace { void CreateExtensionModules(XWalkExtensionClient* client, XWalkModuleSystem* module_system) { - SCOPE_PROFILE(); + const XWalkExtensionClient::ExtensionAPIMap& extensions = + client->extension_apis(); - auto extensions = client->GetExtensions(); for (auto it = extensions.begin(); it != extensions.end(); ++it) { + XWalkExtensionClient::ExtensionCodePoints* codepoint = it->second; std::unique_ptr module( - new XWalkExtensionModule(client, module_system, it->first)); - module_system->RegisterExtensionModule( - std::move(module), it->second->entry_points()); + new XWalkExtensionModule(client, module_system, + it->first, codepoint->api)); + module_system->RegisterExtensionModule(std::move(module), + codepoint->entry_points); } } @@ -44,8 +48,7 @@ XWalkExtensionRendererController::GetInstance() { } XWalkExtensionRendererController::XWalkExtensionRendererController() - : initialized_(false), - extensions_client_(new XWalkExtensionClient()) { + : extensions_client_(new XWalkExtensionClient()) { } XWalkExtensionRendererController::~XWalkExtensionRendererController() { @@ -53,11 +56,9 @@ XWalkExtensionRendererController::~XWalkExtensionRendererController() { void XWalkExtensionRendererController::DidCreateScriptContext( v8::Handle context) { - SCOPE_PROFILE(); XWalkModuleSystem* module_system = new XWalkModuleSystem(context); XWalkModuleSystem::SetModuleSystemInContext( std::unique_ptr(module_system), context); - module_system->RegisterNativeModule( "v8tools", std::unique_ptr(new XWalkV8ToolsModule)); @@ -68,7 +69,9 @@ void XWalkExtensionRendererController::DidCreateScriptContext( "objecttools", std::unique_ptr(new ObjectToolsModule)); + extensions_client_->Initialize(); CreateExtensionModules(extensions_client_.get(), module_system); + module_system->Initialize(); } @@ -78,13 +81,29 @@ void XWalkExtensionRendererController::WillReleaseScriptContext( XWalkModuleSystem::ResetModuleSystemFromContext(context); } -void XWalkExtensionRendererController::InitializeExtensions() { - if (initialized_) { - LOGGER(DEBUG) << "already initialized"; - return; +void XWalkExtensionRendererController::OnReceivedIPCMessage( + const Ewk_IPC_Wrt_Message_Data* data) { + + Eina_Stringshare* type = ewk_ipc_wrt_message_data_type_get(data); + +#define TYPE_BEGIN(x) (!strncmp(type, x, strlen(x))) + if (TYPE_BEGIN("xwalk://")) { + Eina_Stringshare* id = ewk_ipc_wrt_message_data_id_get(data); + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + extensions_client_->OnReceivedIPCMessage(id, msg); + eina_stringshare_del(id); + eina_stringshare_del(msg); + } else { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->HandleMessageFromRuntime(data); } +#undef TYPE_BEGIN + + eina_stringshare_del(type); +} + +void XWalkExtensionRendererController::InitializeExtensionClient() { extensions_client_->Initialize(); - initialized_ = true; } } // namespace extensions diff --git a/extensions/renderer/xwalk_extension_renderer_controller.h b/extensions/renderer/xwalk_extension_renderer_controller.h index ac7d295..b550721 100644 --- a/extensions/renderer/xwalk_extension_renderer_controller.h +++ b/extensions/renderer/xwalk_extension_renderer_controller.h @@ -6,7 +6,9 @@ #ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ #define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ +#include #include + #include #include @@ -21,14 +23,15 @@ class XWalkExtensionRendererController { void DidCreateScriptContext(v8::Handle context); void WillReleaseScriptContext(v8::Handle context); - void InitializeExtensions(); + void OnReceivedIPCMessage(const Ewk_IPC_Wrt_Message_Data* data); + + void InitializeExtensionClient(); private: XWalkExtensionRendererController(); virtual ~XWalkExtensionRendererController(); private: - bool initialized_; std::unique_ptr extensions_client_; }; diff --git a/packaging/crosswalk-tizen.spec b/packaging/crosswalk-tizen.spec index a7091e6..5324e3e 100755 --- a/packaging/crosswalk-tizen.spec +++ b/packaging/crosswalk-tizen.spec @@ -32,7 +32,6 @@ BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(ecore-wayland) BuildRequires: pkgconfig(efl-extension) BuildRequires: pkgconfig(elementary) -BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libwebappenc) BuildRequires: pkgconfig(wgt-manifest-handlers) @@ -43,6 +42,7 @@ BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(uuid) BuildRequires: pkgconfig(launchpad) BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(jsoncpp) %if "%{?profile}" == "mobile" %define tizen_feature_rotary_event_support 0 @@ -122,6 +122,9 @@ install -p -m 755 out/Default/xwalk_runtime %{buildroot}%{_bindir} ln -s %{_bindir}/xwalk_runtime %{buildroot}%{_bindir}/wrt ln -s %{_bindir}/xwalk_runtime %{buildroot}%{_bindir}/wrt-loader +# xwalk extension shared +install -p -m 644 out/Default/lib/libxwalk_extension_shared.so %{buildroot}%{_libdir} + # xwalk_runtime_resources for file in $(find out/Default/gen/locales -type f -name *.mo); do install -m 644 -D $file %{buildroot}%{_datadir}/locale/${file#out/Default/gen/locales/} @@ -141,6 +144,7 @@ rm -fr %{buildroot} %attr(644,root,root) %{_datadir}/edje/xwalk/*.edj %attr(644,root,root) %{_libdir}/libxwalk_tizen_common.so %attr(644,root,root) %{_libdir}/libxwalk_injected_bundle.so +%attr(644,root,root) %{_libdir}/libxwalk_extension_shared.so %attr(644,root,root) %{extension_path}/libwidget_plugin.so %attr(644,root,root) %{extension_path}/widget.json %attr(644,root,root) %{extension_path}/libsplash_screen_plugin.so diff --git a/runtime/browser/preload_manager.cc b/runtime/browser/preload_manager.cc index 5b650b8..9363773 100755 --- a/runtime/browser/preload_manager.cc +++ b/runtime/browser/preload_manager.cc @@ -20,17 +20,16 @@ #include #include -#include "runtime/browser/native_app_window.h" #include "common/logger.h" +#include "runtime/browser/native_app_window.h" +#include "extensions/common/xwalk_extension_server.h" #ifndef INJECTED_BUNDLE_PATH #error INJECTED_BUNDLE_PATH is not set. #endif - namespace runtime { - PreloadManager* PreloadManager::GetInstance() { static PreloadManager instance; return &instance; @@ -40,6 +39,10 @@ PreloadManager::PreloadManager() { } void PreloadManager::CreateCacheComponet() { + // Load extensions in the preload step + auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + extension_server->Preload(); + // It was not used. just to fork zygote process auto context = ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH); diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 2eefcf2..c499533 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -42,7 +42,8 @@ int real_main(int argc, char* argv[]) { const_cast("--no-sandbox"), const_cast("--enable-file-cookies"), const_cast("--allow-file-access-from-files"), - const_cast("--allow-universal-access-from-files") + const_cast("--allow-universal-access-from-files"), + const_cast("--single-process") }; const int chromium_arg_cnt = sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]); @@ -72,7 +73,8 @@ int main(int argc, char* argv[]) { const_cast("--no-sandbox"), const_cast("--enable-file-cookies"), const_cast("--allow-file-access-from-files"), - const_cast("--allow-universal-access-from-files") + const_cast("--allow-universal-access-from-files"), + const_cast("--single-process") }; const int chromium_arg_cnt = sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]); diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index c383366..1996e92 100644 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -43,6 +43,7 @@ #include "runtime/browser/vibration_manager.h" #include "runtime/browser/web_view.h" #include "runtime/browser/splash_screen.h" +#include "extensions/common/xwalk_extension_server.h" #ifndef INJECTED_BUNDLE_PATH #error INJECTED_BUNDLE_PATH is not set. @@ -241,6 +242,10 @@ WebApplication::~WebApplication() { bool WebApplication::Initialize() { SCOPE_PROFILE(); + + auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + extension_server->SetupIPC(ewk_context_); + // ewk setting ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER); @@ -529,65 +534,71 @@ void WebApplication::OnClosedWebView(WebView* view) { void WebApplication::OnReceivedWrtMessage(WebView* /*view*/, Ewk_IPC_Wrt_Message_Data* msg) { - Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(msg); - Eina_Stringshare* msg_ref_id = ewk_ipc_wrt_message_data_reference_id_get(msg); + SCOPE_PROFILE(); Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg); - Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); - - LOGGER(DEBUG) << "RecvMsg: id = " << msg_id; - LOGGER(DEBUG) << "RecvMsg: refid = " << msg_ref_id; - LOGGER(DEBUG) << "RecvMsg: type = " << msg_type; - LOGGER(DEBUG) << "RecvMsg: value = " << msg_value; +#define TYPE_BEGIN(x) (!strncmp(msg_type, x, strlen(x))) #define TYPE_IS(x) (!strcmp(msg_type, x)) - if (TYPE_IS("tizen://hide")) { - // One Way Message - window_->InActive(); - } else if (TYPE_IS("tizen://exit")) { - // One Way Message - ecore_idler_add(ExitAppIdlerCallback, this); - } else if (TYPE_IS("tizen://changeUA")) { - // Async Message - // Change UserAgent of current WebView - bool ret = false; - if (view_stack_.size() > 0 && view_stack_.front() != NULL) { - ret = view_stack_.front()->SetUserAgent(std::string(msg_value)); - } - // Send response - Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_type_set(ans, msg_type); - ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id); - if (ret) - ewk_ipc_wrt_message_data_value_set(ans, "success"); - else - ewk_ipc_wrt_message_data_value_set(ans, "failed"); - if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { - LOGGER(ERROR) << "Failed to send response"; - } - ewk_ipc_wrt_message_data_del(ans); - } else if (TYPE_IS("tizen://deleteAllCookies")) { - Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_type_set(ans, msg_type); - ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id); - if (ClearCookie(ewk_context_)) - ewk_ipc_wrt_message_data_value_set(ans, "success"); - else - ewk_ipc_wrt_message_data_value_set(ans, "failed"); - if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { - LOGGER(ERROR) << "Failed to send response"; + + if (TYPE_BEGIN("xwalk://")) { + auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + extension_server->HandleIPCMessage(msg); + } else { + Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(msg); + Eina_Stringshare* msg_ref_id = + ewk_ipc_wrt_message_data_reference_id_get(msg); + Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); + + if (TYPE_IS("tizen://hide")) { + // One Way Message + window_->InActive(); + } else if (TYPE_IS("tizen://exit")) { + // One Way Message + ecore_idler_add(ExitAppIdlerCallback, this); + } else if (TYPE_IS("tizen://changeUA")) { + // Async Message + // Change UserAgent of current WebView + bool ret = false; + if (view_stack_.size() > 0 && view_stack_.front() != NULL) { + ret = view_stack_.front()->SetUserAgent(std::string(msg_value)); + } + // Send response + Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(ans, msg_type); + ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id); + if (ret) + ewk_ipc_wrt_message_data_value_set(ans, "success"); + else + ewk_ipc_wrt_message_data_value_set(ans, "failed"); + if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { + LOGGER(ERROR) << "Failed to send response"; + } + ewk_ipc_wrt_message_data_del(ans); + } else if (TYPE_IS("tizen://deleteAllCookies")) { + Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(ans, msg_type); + ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id); + if (ClearCookie(ewk_context_)) + ewk_ipc_wrt_message_data_value_set(ans, "success"); + else + ewk_ipc_wrt_message_data_value_set(ans, "failed"); + if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { + LOGGER(ERROR) << "Failed to send response"; + } + ewk_ipc_wrt_message_data_del(ans); + } else if (TYPE_IS("tizen://hide_splash_screen")) { + splash_screen_->HideSplashScreen(SplashScreen::HideReason::CUSTOM); } - ewk_ipc_wrt_message_data_del(ans); - } else if (TYPE_IS("tizen://hide_splash_screen")) { - splash_screen_->HideSplashScreen(SplashScreen::HideReason::CUSTOM); - } + eina_stringshare_del(msg_ref_id); + eina_stringshare_del(msg_id); + eina_stringshare_del(msg_value); + } #undef TYPE_IS +#undef TYPE_BEGIN - eina_stringshare_del(msg_value); eina_stringshare_del(msg_type); - eina_stringshare_del(msg_ref_id); - eina_stringshare_del(msg_id); } void WebApplication::OnOrientationLock( diff --git a/runtime/renderer/injected_bundle.cc b/runtime/renderer/injected_bundle.cc index e3f5730..fa9c972 100755 --- a/runtime/renderer/injected_bundle.cc +++ b/runtime/renderer/injected_bundle.cc @@ -36,24 +36,6 @@ namespace runtime { -static const char* kPreloadLibs[] = { - "/usr/lib/tizen-extensions-crosswalk/libtizen.so", - "/usr/lib/tizen-extensions-crosswalk/libtizen_common.so", - "/usr/lib/tizen-extensions-crosswalk/libtizen_application.so", - "/usr/lib/tizen-extensions-crosswalk/libtizen_utils.so", - NULL -}; - -static void PreloadLibrary() { - for (int i = 0; kPreloadLibs[i]; i++) { - LOGGER(DEBUG) << "Preload libs : " << kPreloadLibs[i]; - void* handle = dlopen(kPreloadLibs[i], RTLD_NOW|RTLD_GLOBAL); - if (handle == nullptr) { - LOGGER(DEBUG) << "Fail to load libs : " << dlerror(); - } - } -} - class BundleGlobalData { public: static BundleGlobalData* GetInstance() { @@ -107,11 +89,6 @@ extern "C" void DynamicSetWidgetInfo(const char* tizen_id) { LOGGER(DEBUG) << "InjectedBundle::DynamicSetWidgetInfo !!" << tizen_id; ecore_init(); - STEP_PROFILE_START("Initialize XWalkExtensionRendererController"); - auto& controller = extensions::XWalkExtensionRendererController::GetInstance(); - controller.InitializeExtensions(); - STEP_PROFILE_END("Initialize XWalkExtensionRendererController"); - runtime::BundleGlobalData::GetInstance()->Initialize(tizen_id); } @@ -189,18 +166,15 @@ extern "C" void DynamicDatabaseAttach(int /*attach*/) { extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& data) { LOGGER(DEBUG) << "InjectedBundle::DynamicOnIPCMessage !!"; - extensions::RuntimeIPCClient* rc = - extensions::RuntimeIPCClient::GetInstance(); - rc->HandleMessageFromRuntime(&data); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.OnReceivedIPCMessage(&data); } extern "C" void DynamicPreloading() { LOGGER(DEBUG) << "InjectedBundle::DynamicPreloading !!"; - runtime::PreloadLibrary(); runtime::BundleGlobalData::GetInstance()->PreInitialize(); - - STEP_PROFILE_START("Initialize XWalkExtensionRendererController"); - auto& controller = extensions::XWalkExtensionRendererController::GetInstance(); - controller.InitializeExtensions(); - STEP_PROFILE_END("Initialize XWalkExtensionRendererController"); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.InitializeExtensionClient(); } diff --git a/runtime/runtime.gyp b/runtime/runtime.gyp index 2c962cd..e93e9e7 100755 --- a/runtime/runtime.gyp +++ b/runtime/runtime.gyp @@ -8,6 +8,7 @@ 'type': 'executable', 'dependencies': [ '../common/common.gyp:xwalk_tizen_common', + '../extensions/extensions.gyp:xwalk_extension_shared', 'resources/resources.gyp:xwalk_runtime_resources', ], 'sources': [ @@ -70,7 +71,7 @@ 'type': 'shared_library', 'dependencies': [ '../common/common.gyp:xwalk_tizen_common', - '../extensions/extensions.gyp:xwalk_extension_renderer', + '../extensions/extensions.gyp:xwalk_extension_shared', ], 'sources': [ 'renderer/injected_bundle.cc',