Add functions to support sending messages to runtime from js.
authorWonYoung Choi <wy80.choi@samsung.com>
Thu, 14 May 2015 06:21:37 +0000 (15:21 +0900)
committerWonYoung Choi <wy80.choi@samsung.com>
Mon, 18 May 2015 02:25:13 +0000 (11:25 +0900)
- bool extension.sendRuntimeMessage(type, value)
- string extension.sendRuntimeSyncMessage(type, value)
- bool extension.sendRuntimeAsyncMessage(type, value, callback)

Change-Id: I50bfdb9f4b5875aad0fd40b850e3295c8dfc7c1e

12 files changed:
src/bundle/CMakeLists.txt
src/bundle/extension_module.cc
src/bundle/extension_module.h
src/bundle/injected_bundle.cc
src/bundle/runtime_ipc_client.cc [new file with mode: 0644]
src/bundle/runtime_ipc_client.h [new file with mode: 0644]
src/runtime/web_application.cc
src/runtime/web_application.h
src/runtime/web_view.cc
src/runtime/web_view.h
src/runtime/web_view_impl.cc
src/runtime/web_view_impl.h

index 4c636a8..484360a 100644 (file)
@@ -30,6 +30,7 @@ SET(TARGET_INJECTED_BUNDLE_SRCS
   ${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})
index ae50939..f4020fb 100644 (file)
@@ -15,6 +15,7 @@
 #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
@@ -74,6 +75,18 @@ ExtensionModule::ExtensionModule(ExtensionClient* client,
       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);
@@ -375,6 +388,102 @@ void ExtensionModule::SetMessageListenerCallback(
 }
 
 // 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();
index dca58de..6a4eb07 100644 (file)
@@ -49,6 +49,12 @@ class ExtensionModule : public ExtensionClient::InstanceHandler {
       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);
index 60e2767..d7fdcab 100755 (executable)
 
 #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 {
@@ -53,7 +54,7 @@ extern "C" void DynamicSetWidgetInfo(const char* tizen_id) {
 
 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*/,
@@ -64,6 +65,11 @@ extern "C" void DynamicPluginStartSession(const char* tizen_id,
     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);
@@ -95,8 +101,10 @@ extern "C" void DynamicDatabaseAttach(const char* tizen_id) {
   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() {
diff --git a/src/bundle/runtime_ipc_client.cc b/src/bundle/runtime_ipc_client.cc
new file mode 100644 (file)
index 0000000..08995ce
--- /dev/null
@@ -0,0 +1,138 @@
+// 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
diff --git a/src/bundle/runtime_ipc_client.h b/src/bundle/runtime_ipc_client.h
new file mode 100644 (file)
index 0000000..91bac59
--- /dev/null
@@ -0,0 +1,73 @@
+// 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
index d118213..ab6d79c 100755 (executable)
@@ -164,6 +164,11 @@ static void InitializeNotificationCallback(Ewk_Context* ewk_context,
                                          app);
 }
 
+static Eina_Bool ExitAppIdlerCallback(void* /*data*/) {
+  elm_exit();
+  return ECORE_CALLBACK_CANCEL;
+}
+
 }  // namespace
 
 WebApplication::WebApplication(
@@ -315,10 +320,10 @@ void WebApplication::Launch(std::unique_ptr<wrt::AppControl> appcontrol) {
   // 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());
@@ -469,10 +474,55 @@ void WebApplication::OnClosedWebView(WebView * view) {
 }
 
 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,
@@ -493,7 +543,7 @@ void WebApplication::OnOrientationLock(WebView* view,
     return;
   }
 
-  if ( lock ) {
+  if (lock) {
     window_->SetRotationLock(preferred_rotation);
   } else {
     window_->SetAutoRotation();
@@ -520,6 +570,7 @@ void WebApplication::OnLanguageChanged() {
 
 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) {
@@ -774,7 +825,8 @@ void WebApplication::HandleDBusMethod(GDBusConnection* /*connection*/,
     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();
index 2f3c6b6..401b9ec 100755 (executable)
@@ -41,7 +41,7 @@ class WebApplication : public WebView::EventListener {
   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);
index aa713da..756ea0b 100755 (executable)
@@ -62,7 +62,7 @@ void WebView::SetAppInfo(const std::string& app_name,
   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
index e2d9a78..8608c75 100755 (executable)
@@ -84,7 +84,7 @@ class WebView {
   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;
index d4066db..90a487a 100755 (executable)
@@ -741,8 +741,8 @@ void WebViewImpl::SetAppInfo(const std::string& app_name,
   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
index 728d53c..ce78e8d 100755 (executable)
@@ -31,7 +31,7 @@ class WebViewImpl {
   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;