1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "runtime/web_view_impl.h"
7 #include <ewk_chromium.h>
11 #include "runtime/native_window.h"
16 // TODO(sngn.lee) : It should be declare in common header
17 const char* kKeyNameBack = "back";
18 const char* kKeyNameMenu = "menu";
20 static int ToWebRotation(int r) {
30 static int ToNativeRotation(int r) {
42 WebViewImpl::WebViewImpl(WebView* view,
53 WebViewImpl::~WebViewImpl() {
55 evas_object_del(ewk_view_);
58 void WebViewImpl::LoadUrl(const std::string& url) {
59 ewk_view_url_set(ewk_view_, url.c_str());
62 void WebViewImpl::Suspend() {
64 ewk_view_suspend(ewk_view_);
67 void WebViewImpl::Resume() {
69 ewk_view_resume(ewk_view_);
72 void WebViewImpl::Reload() {
73 ewk_view_reload(ewk_view_);
76 void WebViewImpl::SetVisibility(bool show) {
77 ewk_view_visibility_set(ewk_view_, show ? EINA_TRUE : EINA_FALSE);
81 bool WebViewImpl::EvalJavascript(const std::string& script) {
82 return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
85 void WebViewImpl::Initialize() {
86 ewk_view_ = ewk_view_add_with_context(window_->evas_object(), context_);
90 InitPolicyDecideCallback();
91 InitQuotaExceededCallback();
92 InitIPCMessageCallback();
93 InitOrientaionLockCallback();
94 InitConsoleMessageCallback();
95 InitCustomContextMenuCallback();
96 InitRotationCallback();
97 InitWindowCreateCallback();
99 // TODO(sngn.lee): "request,certificate,confirm" certification popup
100 // TODO(sngn.lee): ewk_view_notification_permission_callback_set
101 // TODO(sngn.lee): "notification,show"
102 // TODO(sngn.lee): "notification,cancel"
103 // TODO(sngn.lee): "create,window"
104 // TODO(sngn.lee): "close,window"
105 // TODO(sngn.lee): "fullscreen,enterfullscreen"
106 // TODO(sngn.lee): "fullscreen,exitfullscreen"
107 // TODO(sngn.lee): "protocolhandler,registration,requested"
108 // custom protocol handler
109 // TODO(sngn.lee): ewk_view_geolocation_permission_callback_set
110 // TODO(sngn.lee): ewk_view_user_media_permission_callback_set
113 evas_object_show(ewk_view_);
116 void WebViewImpl::Deinitialize() {
117 auto it = smart_callbacks_.begin();
118 for ( ; it != smart_callbacks_.end(); ++it) {
119 evas_object_smart_callback_del(
124 ea_object_event_callback_del(ewk_view_,
126 smart_callbacks_["key_callback"]);
127 ewk_view_exceeded_database_quota_callback_set(
131 ewk_view_exceeded_indexed_database_quota_callback_set(
135 ewk_view_exceeded_local_file_system_quota_callback_set(
139 ewk_view_orientation_lock_callback_set(
143 window_->RemoveRotationHandler(rotation_handler_id_);
146 void WebViewImpl::InitKeyCallback() {
147 auto key_callback = [](void* user_data,
148 Evas_Object* /*obj*/,
149 void* event_info) -> void {
150 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
151 Ea_Callback_Type key = static_cast<Ea_Callback_Type>(
152 reinterpret_cast<int>(event_info));
153 self->OnKeyEvent(key);
155 ea_object_event_callback_add(ewk_view_,
159 ea_object_event_callback_add(ewk_view_,
163 smart_callbacks_["key_callback"] = key_callback;
166 void WebViewImpl::InitLoaderCallback() {
167 // load statred callback
168 auto loadstart_callback = [](void* user_data,
169 Evas_Object* /*obj*/,
171 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
173 self->listener_->OnLoadStart(self->view_);
175 evas_object_smart_callback_add(ewk_view_,
179 // load finished callback
180 auto loadfinished_callback = [](void* user_data,
183 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
185 self->listener_->OnLoadFinished(self->view_);
187 evas_object_smart_callback_add(ewk_view_,
189 loadfinished_callback,
192 // load progress callback
193 auto loadprogress_callback = [](void* user_data,
196 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
197 double* progress = static_cast<double*>(event_info);
199 self->listener_->OnLoadProgress(self->view_, *progress);
201 evas_object_smart_callback_add(ewk_view_,
203 loadprogress_callback,
206 auto rendered_callback = [](void* user_data,
209 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
211 self->listener_->OnRendered(self->view_);
213 evas_object_smart_callback_add(ewk_view_,
217 smart_callbacks_["load,started"] = loadstart_callback;
218 smart_callbacks_["load,finished"] = loadfinished_callback;
219 smart_callbacks_["load,progress"] = loadprogress_callback;
220 smart_callbacks_["frame,rendered"] = rendered_callback;
223 void WebViewImpl::InitPolicyDecideCallback() {
224 // "policy,navigation,decide"
225 auto navigation_decide_callback = [](void* user_data,
228 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
229 Ewk_Policy_Decision* policy =
230 static_cast<Ewk_Policy_Decision*>(event_info);
231 const char* url = ewk_policy_decision_url_get(policy);
233 if (self->listener_) {
234 if (self->listener_->OnDidNavigation(self->view_, url))
235 ewk_policy_decision_use(policy);
237 ewk_policy_decision_ignore(policy);
239 ewk_policy_decision_use(policy);
242 evas_object_smart_callback_add(ewk_view_,
243 "policy,navigation,decide",
244 navigation_decide_callback,
247 // policy,newwindow,decide
248 auto newwindow_decide_callback = [](void* user_data,
251 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
252 Ewk_Policy_Decision* policy =
253 static_cast<Ewk_Policy_Decision*>(event_info);
255 const char* url = ewk_policy_decision_url_get(policy);
257 if (self->listener_) {
258 if (self->listener_->OnDidNavigation(self->view_, url) &&
259 self->listener_->OnDidOpenWindow(self->view_, url)) {
260 ewk_policy_decision_use(policy);
262 ewk_policy_decision_ignore(policy);
265 ewk_policy_decision_use(policy);
268 evas_object_smart_callback_add(ewk_view_,
269 "policy,newwindow,decide",
270 newwindow_decide_callback,
272 smart_callbacks_["policy,navigation,decide"] = navigation_decide_callback;
273 smart_callbacks_["policy,newwindow,decide"] = newwindow_decide_callback;
276 void WebViewImpl::InitQuotaExceededCallback() {
277 // TODO(sngn.lee): Need callback interface - OnQutaExceed
278 // check http://tizen.org/privilege/unlimitedstorage
280 // callback for database quota exceeded
281 auto database_exceeded_callback = [](Evas_Object* view,
282 Ewk_Security_Origin* origin,
285 void*) -> Eina_Bool {
286 std::string protocol(ewk_security_origin_protocol_get(origin));
287 if (protocol == "file" || protocol == "app") {
288 // Allow for local origin
289 ewk_view_exceeded_database_quota_reply(view, EINA_TRUE);
291 // Deny for remote origin
292 ewk_view_exceeded_database_quota_reply(view, EINA_FALSE);
296 ewk_view_exceeded_database_quota_callback_set(
298 database_exceeded_callback,
301 // callback for indexed database quota exceeded
302 auto indexed_db_exceeded_callback = [](Evas_Object* view,
303 Ewk_Security_Origin* origin,
305 void*) -> Eina_Bool {
306 std::string protocol(ewk_security_origin_protocol_get(origin));
307 if (protocol == "file://" || protocol == "app://") {
308 // Allow for local origin
309 ewk_view_exceeded_indexed_database_quota_reply(view, EINA_TRUE);
311 // Deny for remote origin
312 ewk_view_exceeded_indexed_database_quota_reply(view, EINA_FALSE);
316 ewk_view_exceeded_indexed_database_quota_callback_set(
318 indexed_db_exceeded_callback,
321 // callback for localfile quota exceeded
322 auto localfile_exceeded_callback = [](Evas_Object* view,
323 Ewk_Security_Origin* origin,
325 void*) -> Eina_Bool {
326 std::string protocol(ewk_security_origin_protocol_get(origin));
327 if (protocol == "file://" || protocol == "app://") {
328 // Allow for local origin
329 ewk_view_exceeded_local_file_system_quota_reply(view, EINA_TRUE);
331 // Deny for remote origin
332 ewk_view_exceeded_local_file_system_quota_reply(view, EINA_FALSE);
336 ewk_view_exceeded_local_file_system_quota_callback_set(
338 localfile_exceeded_callback,
342 void WebViewImpl::InitIPCMessageCallback() {
344 auto wrt_message_callback = [](void* user_data,
347 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
348 Ewk_IPC_Wrt_Message_Data* msg =
349 static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
351 self->listener_->OnReceivedWrtMessage(self->view_, msg);
353 evas_object_smart_callback_add(ewk_view_,
355 wrt_message_callback,
357 smart_callbacks_["wrt,message"] = wrt_message_callback;
360 void WebViewImpl::InitOrientaionLockCallback() {
361 // Orientation lock callback
362 auto orientation_lock_callback = [](Evas_Object*,
365 void* user_data) -> Eina_Bool {
366 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
367 if (self->listener_) {
368 self->listener_->OnOrientationLock(self->view_,
370 ToNativeRotation(orientation));
374 ewk_view_orientation_lock_callback_set(ewk_view_,
375 orientation_lock_callback,
379 void WebViewImpl::InitConsoleMessageCallback() {
381 auto console_message_callback = [](void* user_data,
384 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
385 if (!self->listener_) {
388 Ewk_Console_Message* msg = static_cast<Ewk_Console_Message*>(event_info);
389 unsigned int line_number = ewk_console_message_line_get(msg);
391 std::stringstream buf;
393 buf << ewk_console_message_source_get(msg) << ":";
394 buf << line_number << ":";
396 buf << ewk_console_message_text_get(msg);
397 int level = ewk_console_message_level_get(msg);
398 self->listener_->OnConsoleMessage(buf.str(), level);
400 evas_object_smart_callback_add(ewk_view_,
402 console_message_callback,
404 smart_callbacks_["console,message"] = console_message_callback;
407 void WebViewImpl::InitCustomContextMenuCallback() {
408 auto custom_context_menu_callback = [](void* user_data,
411 Ewk_Context_Menu* contextmenu = static_cast<Ewk_Context_Menu*>(event_info);
412 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
413 bool disabled = false;
414 if (self->listener_ &&
415 self->listener_->OnContextMenuDisabled(self->view_)) {
418 int cnt = ewk_context_menu_item_count(contextmenu);
419 for (unsigned idx = cnt-1; idx > 0; --idx) {
420 auto* item = ewk_context_menu_nth_item_get(contextmenu, idx);
421 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
423 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
424 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
425 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
426 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
427 case EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_IMAGE_TO_DISK:
428 ewk_context_menu_item_remove(contextmenu, item);
432 ewk_context_menu_item_remove(contextmenu, item);
436 evas_object_smart_callback_add(ewk_view_,
437 "contextmenu,customize",
438 custom_context_menu_callback,
440 smart_callbacks_["contextmenu,customize"] = custom_context_menu_callback;
443 void WebViewImpl::InitRotationCallback() {
445 ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
446 rotation_handler_id_ = window_->AddRotationHandler(
447 std::bind(&WebViewImpl::OnRotation,
449 std::placeholders::_1));
452 void WebViewImpl::InitWindowCreateCallback() {
453 auto create_callback = [](void* user_data,
456 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
457 if (!self->listener_) {
460 WebView* new_view = new WebView(self->window_, self->context_);
461 self->listener_->OnCreatedNewWebView(self->view_, new_view);
464 auto close_callback = [](void* user_data,
467 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
468 if (!self->listener_) {
471 self->listener_->OnClosedWebView(self->view_);
473 evas_object_smart_callback_add(ewk_view_,
477 evas_object_smart_callback_add(ewk_view_,
482 smart_callbacks_["create,window"] = create_callback;
483 smart_callbacks_["close,window"] = close_callback;
486 std::string WebViewImpl::GetUrl() {
487 return std::string(ewk_view_url_get(ewk_view_));
490 Evas_Object* WebViewImpl::evas_object() const {
494 void WebViewImpl::OnRotation(int degree) {
495 ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
498 void WebViewImpl::OnKeyEvent(Ea_Callback_Type key_type) {
500 if (key_type == EA_CALLBACK_BACK) {
501 if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
504 keyname = kKeyNameBack;
505 } else if (key_type == EA_CALLBACK_MORE) {
506 keyname = kKeyNameMenu;
512 listener_->OnHardwareKey(view_, keyname);
515 void WebViewImpl::SetEventListener(WebView::EventListener* listener) {
516 listener_ = listener;
519 void WebViewImpl::SetAppInfo(const std::string& app_name,
520 const std::string& version) {
521 std::string ua = app_name + "/" + version;
522 ewk_view_application_name_for_user_agent_set(ewk_view_, ua.c_str());
524 void WebViewImpl::SetUserAgent(const std::string& user_agent) {
525 ewk_view_user_agent_set(ewk_view_, user_agent.c_str());