'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',
'capi-appfw-package-manager',
'capi-system-system-settings',
'dlog',
- 'gio-2.0',
'uuid',
'libwebappenc',
'manifest-parser',
'variables': {
'packages': [
'dlog',
- 'gio-2.0',
],
},
},
+++ /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.
- */
-
-#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<DBusClient*>(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
+++ /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_COMMON_DBUS_CLIENT_H_
-#define XWALK_COMMON_DBUS_CLIENT_H_
-
-#include <gio/gio.h>
-#include <glib.h>
-
-#include <functional>
-#include <map>
-#include <string>
-
-namespace common {
-
-class DBusClient {
- public:
- typedef std::function<void(const std::string& signal,
- GVariant* parameters)> 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<std::string, SignalCallback> signal_callbacks_;
-};
-
-} // namespace common
-
-#endif // XWALK_COMMON_DBUS_CLIENT_H_
+++ /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.
- */
-
-#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<DBusServer*>(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<DBusServer*>(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<DBusServer*>(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<DBusServer*>(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<DBusServer*>(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
+++ /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_COMMON_DBUS_SERVER_H_
-#define XWALK_COMMON_DBUS_SERVER_H_
-
-#include <gio/gio.h>
-#include <glib.h>
-#include <functional>
-#include <map>
-#include <string>
-
-namespace common {
-
-class DBusServer {
- public:
- typedef std::function<bool(GCredentials* creds)> PeerCredentialsCallback;
- typedef std::function<void(GDBusConnection* connection,
- const std::string& method_name,
- GVariant* parameters,
- GDBusMethodInvocation* invocation)> MethodCallback;
- typedef std::function<GVariant*(GDBusConnection* connection,
- const gchar* property)> PropertyGetter;
- typedef std::function<bool(GDBusConnection* connection,
- const gchar* property,
- GVariant* value)> PropertySetter;
- typedef std::function<void(GDBusConnection* connection)> 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<std::string, MethodCallback> method_callbacks_;
- std::map<std::string, PropertyGetter> property_getters_;
- std::map<std::string, PropertySetter> property_setters_;
-};
-
-} // namespace common
-
-#endif // XWALK_COMMON_DBUS_SERVER_H_
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
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
#include "extensions/common/xwalk_extension_manager.h"
#include <glob.h>
+#include <dlfcn.h>
#include <fstream>
#include <set>
#include "extensions/common/constants.h"
#include "extensions/common/xwalk_extension.h"
+#ifndef EXTENSION_PATH
+ #error EXTENSION_PATH is not set.
+#endif
+
namespace extensions {
namespace {
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() {
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("/");
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()) {
typedef std::map<std::string, XWalkExtension*> 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);
--- /dev/null
+// 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 <Ecore.h>
+
+#include <string>
+
+#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
--- /dev/null
+// 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 <ewk_chromium.h>
+#include <json/json.h>
+
+#include <string>
+#include <map>
+
+#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<std::string, XWalkExtensionInstance*> InstanceMap;
+
+ Ewk_Context* ewk_context_;
+
+ XWalkExtensionManager manager_;
+
+ InstanceMap instances_;
+};
+
+} // namespace extensions
+
+#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_
],
'targets': [
{
- 'target_name': 'xwalk_extension_renderer',
- 'type': 'static_library',
+ 'target_name': 'xwalk_extension_shared',
+ 'type': 'shared_library',
'dependencies': [
'../common/common.gyp:xwalk_tizen_common',
],
'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',
'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',
#include "extensions/renderer/runtime_ipc_client.h"
#include "common/logger.h"
+#include "common/profiler.h"
#include "common/string_utils.h"
namespace extensions {
void RuntimeIPCClient::SendMessage(v8::Handle<v8::Context> context,
const std::string& type,
const std::string& value) {
+ SendMessage(context, type, "", "", value);
+}
+
+void RuntimeIPCClient::SendMessage(v8::Handle<v8::Context> context,
+ const std::string& type,
+ const std::string& id,
+ const std::string& value) {
+ SendMessage(context, type, id, "", value);
+}
+
+void RuntimeIPCClient::SendMessage(v8::Handle<v8::Context> 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);
std::string RuntimeIPCClient::SendSyncMessage(v8::Handle<v8::Context> context,
const std::string& type,
const std::string& value) {
+ return SendSyncMessage(context, type, "", "", value);
+}
+
+std::string RuntimeIPCClient::SendSyncMessage(v8::Handle<v8::Context> 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<v8::Context> 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;
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();
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;
// Send message to BrowserProcess without reply
void SendMessage(v8::Handle<v8::Context> context,
- const std::string& type, const std::string& value);
+ const std::string& type,
+ const std::string& value);
+
+ void SendMessage(v8::Handle<v8::Context> context,
+ const std::string& type,
+ const std::string& id,
+ const std::string& value);
+
+ void SendMessage(v8::Handle<v8::Context> 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<v8::Context> context,
const std::string& type,
const std::string& value);
+ std::string SendSyncMessage(v8::Handle<v8::Context> context,
+ const std::string& type,
+ const std::string& id,
+ const std::string& value);
+
+ std::string SendSyncMessage(v8::Handle<v8::Context> 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<v8::Context> context,
#include "extensions/renderer/xwalk_extension_client.h"
-#include <gio/gio.h>
-#include <glib.h>
+#include <Ecore.h>
#include <unistd.h>
+#include <v8/v8.h>
+#include <json/json.h>
#include <string>
#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<const char*>(data);
+ XWalkExtensionServer* server = XWalkExtensionServer::GetInstance();
+ std::string instance_id = server->CreateInstance(extension_name);
+ return static_cast<void*>(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<v8::Context> 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<void*>(const_cast<char*>(extension_name.data())));
+ std::string* sp = static_cast<std::string*>(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<v8::Context> 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<v8::Context> 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<v8::Context> 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<v8::Context> 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
#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_
#define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_
+#include <v8/v8.h>
+
#include <map>
#include <memory>
#include <string>
#include <vector>
-#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<std::string, XWalkExtension*> ExtensionMap;
- typedef std::map<std::string, XWalkExtensionInstance*> InstanceMap;
-
struct InstanceHandler {
virtual void HandleMessageFromNative(const std::string& msg) = 0;
protected:
void Initialize();
- XWalkExtension* GetExtension(const std::string& extension_name);
- ExtensionMap GetExtensions();
-
- std::string CreateInstance(const std::string& extension_name,
+ std::string CreateInstance(v8::Handle<v8::Context> context,
+ const std::string& extension_name,
InstanceHandler* handler);
- void DestroyInstance(const std::string& instance_id);
+ void DestroyInstance(v8::Handle<v8::Context> context,
+ const std::string& instance_id);
- void PostMessageToNative(const std::string& instance_id,
+ void PostMessageToNative(v8::Handle<v8::Context> context,
+ const std::string& instance_id,
const std::string& msg);
- std::string SendSyncMessageToNative(const std::string& instance_id,
+ std::string SendSyncMessageToNative(v8::Handle<v8::Context> context,
+ const std::string& instance_id,
const std::string& msg);
+ std::string GetAPIScript(v8::Handle<v8::Context> context,
+ const std::string& extension_name);
+
+ void OnReceivedIPCMessage(const std::string& instance_id,
+ const std::string& msg);
+
+ struct ExtensionCodePoints {
+ std::string api;
+ std::vector<std::string> entry_points;
+ };
+
+ typedef std::map<std::string, ExtensionCodePoints*> ExtensionAPIMap;
+
+ const ExtensionAPIMap& extension_apis() const { return extension_apis_; }
+
private:
- XWalkExtensionManager manager_;
- InstanceMap instances_;
+ ExtensionAPIMap extension_apis_;
+
+ typedef std::map<std::string, InstanceHandler*> HandlerMap;
+ HandlerMap handlers_;
};
} // namespace extensions
#include <vector>
#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"
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<v8::Object> function_data = v8::Object::New(isolate);
message_listener_.Reset();
if (!instance_id_.empty())
- client_->DestroyInstance(instance_id_);
+ client_->DestroyInstance(module_system_->GetV8Context(), instance_id_);
}
namespace {
void XWalkExtensionModule::LoadExtensionCode(
v8::Handle<v8::Context> context, v8::Handle<v8::Function> 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<v8::Value> result = RunString(wrapped_api_code, &exception);
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);
}
// 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.
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<v8::Object>, and
v8::Persistent<v8::Function> message_listener_;
std::string extension_name_;
+ std::string extension_code_;
XWalkExtensionClient* client_;
XWalkModuleSystem* module_system_;
#include "extensions/renderer/xwalk_extension_renderer_controller.h"
+#include <Ecore.h>
#include <v8/v8.h>
#include <string>
#include <utility>
#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 {
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<XWalkExtensionModule> 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);
}
}
}
XWalkExtensionRendererController::XWalkExtensionRendererController()
- : initialized_(false),
- extensions_client_(new XWalkExtensionClient()) {
+ : extensions_client_(new XWalkExtensionClient()) {
}
XWalkExtensionRendererController::~XWalkExtensionRendererController() {
void XWalkExtensionRendererController::DidCreateScriptContext(
v8::Handle<v8::Context> context) {
- SCOPE_PROFILE();
XWalkModuleSystem* module_system = new XWalkModuleSystem(context);
XWalkModuleSystem::SetModuleSystemInContext(
std::unique_ptr<XWalkModuleSystem>(module_system), context);
-
module_system->RegisterNativeModule(
"v8tools",
std::unique_ptr<XWalkNativeModule>(new XWalkV8ToolsModule));
"objecttools",
std::unique_ptr<XWalkNativeModule>(new ObjectToolsModule));
+ extensions_client_->Initialize();
CreateExtensionModules(extensions_client_.get(), module_system);
+
module_system->Initialize();
}
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
#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_
#define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_
+#include <ewk_chromium.h>
#include <v8/v8.h>
+
#include <memory>
#include <string>
void DidCreateScriptContext(v8::Handle<v8::Context> context);
void WillReleaseScriptContext(v8::Handle<v8::Context> context);
- void InitializeExtensions();
+ void OnReceivedIPCMessage(const Ewk_IPC_Wrt_Message_Data* data);
+
+ void InitializeExtensionClient();
private:
XWalkExtensionRendererController();
virtual ~XWalkExtensionRendererController();
private:
- bool initialized_;
std::unique_ptr<XWalkExtensionClient> extensions_client_;
};
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)
BuildRequires: pkgconfig(uuid)
BuildRequires: pkgconfig(launchpad)
BuildRequires: pkgconfig(ttrace)
+BuildRequires: pkgconfig(jsoncpp)
%if "%{?profile}" == "mobile"
%define tizen_feature_rotary_event_support 0
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/}
%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
#include <ewk_chromium.h>
#include <stdio.h>
-#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;
}
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);
const_cast<char*>("--no-sandbox"),
const_cast<char*>("--enable-file-cookies"),
const_cast<char*>("--allow-file-access-from-files"),
- const_cast<char*>("--allow-universal-access-from-files")
+ const_cast<char*>("--allow-universal-access-from-files"),
+ const_cast<char*>("--single-process")
};
const int chromium_arg_cnt =
sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]);
const_cast<char*>("--no-sandbox"),
const_cast<char*>("--enable-file-cookies"),
const_cast<char*>("--allow-file-access-from-files"),
- const_cast<char*>("--allow-universal-access-from-files")
+ const_cast<char*>("--allow-universal-access-from-files"),
+ const_cast<char*>("--single-process")
};
const int chromium_arg_cnt =
sizeof(chromium_arg_options) / sizeof(chromium_arg_options[0]);
#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.
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);
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(
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() {
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);
}
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();
}
'type': 'executable',
'dependencies': [
'../common/common.gyp:xwalk_tizen_common',
+ '../extensions/extensions.gyp:xwalk_extension_shared',
'resources/resources.gyp:xwalk_runtime_resources',
],
'sources': [
'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',