${BASE_SRCDIR}/bundle/extension_client.cc
${BASE_SRCDIR}/bundle/extension_module.cc
${BASE_SRCDIR}/bundle/module_system.cc
+ ${BASE_SRCDIR}/bundle/runtime_ipc_client.cc
)
INCLUDE_DIRECTORIES(${TARGET_INJECTED_BUNDLE_INCS})
#include "common/logger.h"
#include "bundle/extension_client.h"
#include "bundle/module_system.h"
+#include "bundle/runtime_ipc_client.h"
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
v8::String::NewFromUtf8(isolate, "setMessageListener"),
v8::FunctionTemplate::New(
isolate, SetMessageListenerCallback, function_data));
+ object_template->Set(
+ v8::String::NewFromUtf8(isolate, "sendRuntimeMessage"),
+ v8::FunctionTemplate::New(
+ isolate, SendRuntimeMessageCallback, function_data));
+ object_template->Set(
+ v8::String::NewFromUtf8(isolate, "sendRuntimeSyncMessage"),
+ v8::FunctionTemplate::New(
+ isolate, SendRuntimeSyncMessageCallback, function_data));
+ object_template->Set(
+ v8::String::NewFromUtf8(isolate, "sendRuntimeAsyncMessage"),
+ v8::FunctionTemplate::New(
+ isolate, SendRuntimeAsyncMessageCallback, function_data));
function_data_.Reset(isolate, function_data);
object_template_.Reset(isolate, object_template);
}
// static
+void ExtensionModule::SendRuntimeMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::ReturnValue<v8::Value> result(info.GetReturnValue());
+ ExtensionModule* module = GetExtensionModule(info);
+ if (!module || info.Length() < 1) {
+ result.Set(false);
+ return;
+ }
+
+ v8::String::Utf8Value type(info[0]->ToString());
+ std::string data_str;
+ if (info.Length() > 1) {
+ v8::String::Utf8Value data(info[1]->ToString());
+ data_str = std::string(*data);
+ }
+
+ RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance();
+ rc->SendMessage(std::string(*type), data_str);
+
+ result.Set(true);
+}
+
+// static
+void ExtensionModule::SendRuntimeSyncMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+
+ v8::ReturnValue<v8::Value> result(info.GetReturnValue());
+ ExtensionModule* module = GetExtensionModule(info);
+ if (!module || info.Length() < 1) {
+ result.SetUndefined();
+ return;
+ }
+
+ v8::String::Utf8Value type(info[0]->ToString());
+ std::string data_str;
+ if (info.Length() > 1) {
+ v8::String::Utf8Value data(info[1]->ToString());
+ data_str = std::string(*data);
+ }
+
+ RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance();
+ std::string reply = rc->SendSyncMessage(std::string(*type), data_str);
+
+ result.Set(v8::String::NewFromUtf8(isolate, reply.c_str()));
+}
+
+// static
+void ExtensionModule::SendRuntimeAsyncMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::ReturnValue<v8::Value> result(info.GetReturnValue());
+ ExtensionModule* module = GetExtensionModule(info);
+ if (!module || info.Length() < 1) {
+ result.Set(false);
+ return;
+ }
+
+ // type
+ v8::String::Utf8Value type(info[0]->ToString());
+
+ // value
+ std::string value_str;
+ if (info.Length() > 1) {
+ v8::String::Utf8Value value(info[1]->ToString());
+ value_str = std::string(*value);
+ }
+
+ // callback
+ RuntimeIPCClient::JSCallback* js_callback = NULL;
+ if (info.Length() > 2) {
+ if (info[2]->IsFunction()) {
+ v8::Handle<v8::Function> func = info[2].As<v8::Function>();
+ js_callback = new RuntimeIPCClient::JSCallback(isolate, func);
+ }
+ }
+
+ auto callback = [](const std::string& /*type*/,
+ const std::string& value,
+ RuntimeIPCClient::JSCallback* js_callback) -> void {
+ if (js_callback) {
+ v8::Handle<v8::Value> args[] = {
+ v8::String::NewFromUtf8(js_callback->isolate(), value.c_str()) };
+ js_callback->Call(args);
+ }
+ };
+
+ RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance();
+ rc->SendAsyncMessage(std::string(*type), value_str, callback, js_callback);
+
+ result.Set(true);
+}
+
+// static
ExtensionModule* ExtensionModule::GetExtensionModule(
const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
const v8::FunctionCallbackInfo<v8::Value>& info);
static void SetMessageListenerCallback(
const v8::FunctionCallbackInfo<v8::Value>& info);
+ static void SendRuntimeMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info);
+ static void SendRuntimeSyncMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info);
+ static void SendRuntimeAsyncMessageCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info);
static ExtensionModule* GetExtensionModule(
const v8::FunctionCallbackInfo<v8::Value>& info);
#include "common/logger.h"
#include "common/string_utils.h"
-#include "bundle/extension_renderer_controller.h"
#include "common/application_data.h"
#include "common/resource_manager.h"
#include "common/locale_manager.h"
+#include "bundle/runtime_ipc_client.h"
+#include "bundle/extension_renderer_controller.h"
namespace wrt {
class BundleGlobalData {
extern "C" void DynamicPluginStartSession(const char* tizen_id,
v8::Handle<v8::Context> context,
- int /*routing_handle*/,
+ int routing_handle,
double /*scale*/,
const char* uuid,
const char* /*theme*/,
return;
}
+ // Initialize RuntimeIPCClient
+ wrt::RuntimeIPCClient* rc = wrt::RuntimeIPCClient::GetInstance();
+ rc->set_routing_id(routing_handle);
+
+ // Initialize ExtensionRendererController
wrt::ExtensionRendererController& controller =
wrt::ExtensionRendererController::GetInstance();
controller.InitializeExtensions(uuid);
LOGGER(DEBUG) << "InjectedBundle::DynamicDatabaseAttach !!" << tizen_id;
}
-extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& /*data*/) {
+extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& data) {
LOGGER(DEBUG) << "InjectedBundle::DynamicOnIPCMessage !!";
+ wrt::RuntimeIPCClient* rc = wrt::RuntimeIPCClient::GetInstance();
+ rc->HandleMessageFromRuntime(&data);
}
extern "C" void DynamicPreloading() {
--- /dev/null
+// Copyright 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 "bundle/runtime_ipc_client.h"
+
+#include "common/logger.h"
+#include "common/string_utils.h"
+
+namespace wrt {
+
+RuntimeIPCClient::JSCallback::JSCallback(v8::Isolate* isolate,
+ v8::Handle<v8::Function> callback)
+ : isolate_(isolate) {
+ callback_.Reset(isolate, callback);
+}
+
+RuntimeIPCClient::JSCallback::~JSCallback() {
+ callback_.Reset();
+}
+
+void RuntimeIPCClient::JSCallback::Call(v8::Handle<v8::Value> args[]) {
+ if (!callback_.IsEmpty()) {
+ v8::HandleScope handle_scope(isolate_);
+ v8::Handle<v8::Function> func =
+ v8::Local<v8::Function>::New(isolate_, callback_);
+ func->Call(func, 1, args);
+ }
+}
+
+// static
+RuntimeIPCClient* RuntimeIPCClient::GetInstance() {
+ static RuntimeIPCClient self;
+ return &self;
+}
+
+RuntimeIPCClient::RuntimeIPCClient() : routing_id_(0) {
+}
+
+void RuntimeIPCClient::SendMessage(const std::string& type,
+ const std::string& value) {
+ 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_value_set(msg, value.c_str());
+
+ 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);
+}
+
+std::string RuntimeIPCClient::SendSyncMessage(const std::string& type,
+ const std::string& value) {
+ 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());
+
+ 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();
+ }
+ }
+
+ 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;
+}
+
+void RuntimeIPCClient::SendAsyncMessage(const std::string& type,
+ const std::string& value,
+ ReplyCallback callback,
+ JSCallback* js_callback) {
+ std::string msg_id = utils::GenerateUUID();
+
+ Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new();
+ ewk_ipc_wrt_message_data_id_set(msg, msg_id.c_str());
+ ewk_ipc_wrt_message_data_type_set(msg, type.c_str());
+ ewk_ipc_wrt_message_data_value_set(msg, value.c_str());
+
+ 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;
+ }
+ }
+
+ callbacks_[msg_id].callback = callback;
+ callbacks_[msg_id].js_callback = js_callback;
+
+ ewk_ipc_wrt_message_data_del(msg);
+}
+
+void RuntimeIPCClient::HandleMessageFromRuntime(
+ const Ewk_IPC_Wrt_Message_Data* msg) {
+ if (msg == NULL) {
+ LOGGER(ERROR) << "received message is NULL";
+ return;
+ }
+
+ Eina_Stringshare* msg_refid = ewk_ipc_wrt_message_data_reference_id_get(msg);
+
+ if (msg_refid == NULL || !strcmp(msg_refid,"")) {
+ if (msg_refid) eina_stringshare_del(msg_refid);
+ LOGGER(ERROR) << "No reference id of received message.";
+ return;
+ }
+
+ auto it = callbacks_.find(msg_refid);
+ if (it == callbacks_.end()) {
+ eina_stringshare_del(msg_refid);
+ LOGGER(ERROR) << "No registered callback with reference id : " << msg_refid;
+ return;
+ }
+
+ Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg);
+ Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg);
+
+ const AsyncData& async_data = it->second;
+ async_data.callback(msg_type, msg_value, async_data.js_callback);
+ callbacks_.erase(it);
+
+ eina_stringshare_del(msg_refid);
+ eina_stringshare_del(msg_type);
+ eina_stringshare_del(msg_value);
+}
+
+} // namespace wrt
--- /dev/null
+// Copyright 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 WRT_BUNDLE_RUNTIME_IPC_CLIENT_H_
+#define WRT_BUNDLE_RUNTIME_IPC_CLIENT_H_
+
+#include <v8/v8.h>
+#include <ewk_ipc_message.h>
+#include <functional>
+#include <map>
+#include <string>
+
+namespace wrt {
+
+class RuntimeIPCClient {
+ public:
+ class JSCallback {
+ public:
+ explicit JSCallback(v8::Isolate* isolate,
+ v8::Handle<v8::Function> callback);
+ ~JSCallback();
+
+ v8::Isolate* isolate() const { return isolate_; }
+
+ void Call(v8::Handle<v8::Value> args[]);
+ private:
+ v8::Isolate* isolate_;
+ v8::Persistent<v8::Function> callback_;
+ };
+
+ typedef std::function<void(const std::string& type,
+ const std::string& value,
+ JSCallback* js_callback)> ReplyCallback;
+
+ static RuntimeIPCClient* GetInstance();
+
+ // Send message to BrowserProcess without reply
+ void SendMessage(const std::string& type, const std::string& value);
+
+ // Send message to BrowserProcess synchronous with reply
+ std::string SendSyncMessage(const std::string& type, const std::string& value);
+
+ // Send message to BrowserProcess asynchronous,
+ // reply message will be passed to callback function.
+ void SendAsyncMessage(const std::string& type, const std::string& value,
+ ReplyCallback callback, JSCallback* js_callback);
+
+ void HandleMessageFromRuntime(const Ewk_IPC_Wrt_Message_Data* msg);
+
+ int routing_id() const { return routing_id_; }
+ void set_routing_id(int routing_id) { routing_id_ = routing_id; }
+
+ private:
+ class AsyncData {
+ public:
+ ~AsyncData() {
+ if (js_callback) delete js_callback;
+ }
+
+ ReplyCallback callback;
+ JSCallback* js_callback;
+ };
+
+ RuntimeIPCClient();
+
+ int routing_id_;
+ std::map<std::string, AsyncData> callbacks_;
+};
+
+} // namespace
+
+#endif // WRT_BUNDLE_RUNTIME_IPC_CLIENT_H_
\ No newline at end of file
app);
}
+static Eina_Bool ExitAppIdlerCallback(void* /*data*/) {
+ elm_exit();
+ return ECORE_CALLBACK_CANCEL;
+}
+
} // namespace
WebApplication::WebApplication(
// TODO(wy80.choi): ewk_send_widget_info should be fixed to receive uuid of
// application instead of widget_id.
// Currently, uuid is passed as encoded_bundle argument temporarily.
- // ewk_send_widget_info(ewk_context_, 1,
- // elm_config_scale_get(),
- // elm_theme_get(NULL),
- // app_uuid_.c_str());
+ ewk_send_widget_info(ewk_context_, appid_.c_str(),
+ elm_config_scale_get(),
+ elm_theme_get(NULL),
+ app_uuid_.c_str());
std::unique_ptr<ResourceManager::Resource> res =
resource_manager_->GetStartResource(appcontrol.get());
}
void WebApplication::OnReceivedWrtMessage(
- WebView* /*view*/,
- Ewk_IPC_Wrt_Message_Data* /*message*/) {
- // TODO(wy80.choi) : Handle messages from injected bundle?
- // ex. SendRuntimeMessage to hide / exit application.
+ 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);
+ 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_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, NULL);
+ } 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://test-sync")) {
+ // TODO(wy80.choi): this type should be removed after finish test
+ ewk_ipc_wrt_message_data_value_set(msg, "reply!!");
+ }
+ #undef TYPE_IS
+
+ eina_stringshare_del(msg_value);
+ eina_stringshare_del(msg_type);
+ eina_stringshare_del(msg_ref_id);
+ eina_stringshare_del(msg_id);
}
void WebApplication::OnOrientationLock(WebView* view,
return;
}
- if ( lock ) {
+ if (lock) {
window_->SetRotationLock(preferred_rotation);
} else {
window_->SetAutoRotation();
void WebApplication::OnConsoleMessage(const std::string& msg, int level) {
static bool enabled = (getenv(kConsoleLogEnableKey) != NULL);
+ enabled = true;
if (debug_mode_ || enabled) {
int dlog_level = DLOG_DEBUG;
switch (level) {
if (g_strcmp0(key, "runtime_name") == 0) {
value = std::string("wrt");
} else if (g_strcmp0(key, "app_id") == 0) {
- // TODO(wy80.choi): TEC requries double quotes, but webapi-plugins is not.
+ // TODO(wy80.choi): TEC requries double quotes,
+ // but webapi-plugins doesn't. It should be fixed.
value = "\"" + appid_ + "\"";
} else if (g_strcmp0(key, "encoded_bundle") == 0) {
value = received_appcontrol_->encoded_bundle();
virtual void OnCreatedNewWebView(WebView* view, WebView* new_view);
virtual void OnClosedWebView(WebView * view);
virtual void OnReceivedWrtMessage(WebView* view,
- Ewk_IPC_Wrt_Message_Data* message);
+ Ewk_IPC_Wrt_Message_Data* msg);
virtual void OnOrientationLock(WebView* view,
bool lock,
int preferred_rotation);
impl_->SetAppInfo(app_name, version);
}
-void WebView::SetUserAgent(const std::string& user_agent) {
- impl_->SetUserAgent(user_agent.c_str());
+bool WebView::SetUserAgent(const std::string& user_agent) {
+ return impl_->SetUserAgent(user_agent.c_str());
}
} // namespace wrt
void SetVisibility(bool show);
bool EvalJavascript(const std::string& script);
void SetAppInfo(const std::string& app_name, const std::string& version);
- void SetUserAgent(const std::string& user_agent);
+ bool SetUserAgent(const std::string& user_agent);
void SetEventListener(EventListener* listener);
Evas_Object* evas_object() const;
std::string ua = app_name + "/" + version;
ewk_view_application_name_for_user_agent_set(ewk_view_, ua.c_str());
}
-void WebViewImpl::SetUserAgent(const std::string& user_agent) {
- ewk_view_user_agent_set(ewk_view_, user_agent.c_str());
+bool WebViewImpl::SetUserAgent(const std::string& user_agent) {
+ return ewk_view_user_agent_set(ewk_view_, user_agent.c_str());
}
} // namespace wrt
void SetVisibility(bool show);
bool EvalJavascript(const std::string& script);
void SetAppInfo(const std::string& app_name, const std::string& version);
- void SetUserAgent(const std::string& user_agent);
+ bool SetUserAgent(const std::string& user_agent);
void SetEventListener(WebView::EventListener* listener);
Evas_Object* evas_object() const;