2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "runtime/web_view_impl.h"
20 #include <ewk_chromium.h>
24 #include "runtime/native_window.h"
25 #include "common/logger.h"
30 // TODO(sngn.lee) : It should be declare in common header
31 const char* kKeyNameBack = "back";
32 const char* kKeyNameMenu = "menu";
34 static int ToWebRotation(int r) {
44 static int ToNativeRotation(int r) {
56 WebViewImpl::WebViewImpl(WebView* view,
68 WebViewImpl::~WebViewImpl() {
70 evas_object_del(ewk_view_);
73 void WebViewImpl::LoadUrl(const std::string& url) {
74 ewk_view_url_set(ewk_view_, url.c_str());
77 void WebViewImpl::Suspend() {
79 ewk_view_suspend(ewk_view_);
82 void WebViewImpl::Resume() {
84 ewk_view_resume(ewk_view_);
87 void WebViewImpl::Reload() {
88 ewk_view_reload(ewk_view_);
91 void WebViewImpl::SetVisibility(bool show) {
92 ewk_view_visibility_set(ewk_view_, show ? EINA_TRUE : EINA_FALSE);
96 bool WebViewImpl::EvalJavascript(const std::string& script) {
97 return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
100 void WebViewImpl::Initialize() {
101 ewk_view_ = ewk_view_add_with_context(window_->evas_object(), context_);
104 InitLoaderCallback();
105 InitPolicyDecideCallback();
106 InitQuotaExceededCallback();
107 InitIPCMessageCallback();
108 InitOrientaionLockCallback();
109 InitConsoleMessageCallback();
110 InitCustomContextMenuCallback();
111 InitRotationCallback();
112 InitWindowCreateCallback();
113 InitFullscreenCallback();
114 InitNotificationPermissionCallback();
115 InitGeolocationPermissionCallback();
116 InitAuthenticationCallback();
117 InitCertificateAllowCallback();
119 // TODO(sngn.lee): "notification,show"
120 // TODO(sngn.lee): "notification,cancel"
121 // TODO(sngn.lee): "protocolhandler,registration,requested"
122 // custom protocol handler
123 // TODO(sngn.lee): ewk_view_user_media_permission_callback_set
126 evas_object_show(ewk_view_);
129 void WebViewImpl::Deinitialize() {
130 auto it = smart_callbacks_.begin();
131 for ( ; it != smart_callbacks_.end(); ++it) {
132 evas_object_smart_callback_del(
137 ea_object_event_callback_del(ewk_view_,
139 smart_callbacks_["key_callback"]);
140 ewk_view_exceeded_database_quota_callback_set(
144 ewk_view_exceeded_indexed_database_quota_callback_set(
148 ewk_view_exceeded_local_file_system_quota_callback_set(
152 ewk_view_orientation_lock_callback_set(
156 ewk_view_notification_permission_callback_set(
160 ewk_view_geolocation_permission_callback_set(
164 window_->RemoveRotationHandler(rotation_handler_id_);
167 void WebViewImpl::InitKeyCallback() {
168 auto key_callback = [](void* user_data,
169 Evas_Object* /*obj*/,
170 void* event_info) -> void {
171 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
172 Ea_Callback_Type key = static_cast<Ea_Callback_Type>(
173 *static_cast<int*>(event_info));
174 self->OnKeyEvent(key);
176 ea_object_event_callback_add(ewk_view_,
180 ea_object_event_callback_add(ewk_view_,
184 smart_callbacks_["key_callback"] = key_callback;
187 void WebViewImpl::InitLoaderCallback() {
188 // load statred callback
189 auto loadstart_callback = [](void* user_data,
190 Evas_Object* /*obj*/,
192 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
194 self->listener_->OnLoadStart(self->view_);
196 evas_object_smart_callback_add(ewk_view_,
200 // load finished callback
201 auto loadfinished_callback = [](void* user_data,
204 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
206 self->listener_->OnLoadFinished(self->view_);
208 evas_object_smart_callback_add(ewk_view_,
210 loadfinished_callback,
213 // load progress callback
214 auto loadprogress_callback = [](void* user_data,
217 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
218 double* progress = static_cast<double*>(event_info);
220 self->listener_->OnLoadProgress(self->view_, *progress);
222 evas_object_smart_callback_add(ewk_view_,
224 loadprogress_callback,
227 auto rendered_callback = [](void* user_data,
230 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
232 self->listener_->OnRendered(self->view_);
234 evas_object_smart_callback_add(ewk_view_,
238 smart_callbacks_["load,started"] = loadstart_callback;
239 smart_callbacks_["load,finished"] = loadfinished_callback;
240 smart_callbacks_["load,progress"] = loadprogress_callback;
241 smart_callbacks_["frame,rendered"] = rendered_callback;
244 void WebViewImpl::InitPolicyDecideCallback() {
245 // "policy,navigation,decide"
246 auto navigation_decide_callback = [](void* user_data,
249 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
250 Ewk_Policy_Decision* policy =
251 static_cast<Ewk_Policy_Decision*>(event_info);
252 const char* url = ewk_policy_decision_url_get(policy);
254 if (self->listener_) {
255 if (self->listener_->OnDidNavigation(self->view_, url))
256 ewk_policy_decision_use(policy);
258 ewk_policy_decision_ignore(policy);
260 ewk_policy_decision_use(policy);
263 evas_object_smart_callback_add(ewk_view_,
264 "policy,navigation,decide",
265 navigation_decide_callback,
268 // policy,newwindow,decide
269 auto newwindow_decide_callback = [](void* user_data,
272 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
273 Ewk_Policy_Decision* policy =
274 static_cast<Ewk_Policy_Decision*>(event_info);
276 const char* url = ewk_policy_decision_url_get(policy);
278 if (self->listener_) {
279 if (self->listener_->OnDidNavigation(self->view_, url) &&
280 self->listener_->OnDidOpenWindow(self->view_, url)) {
281 ewk_policy_decision_use(policy);
283 ewk_policy_decision_ignore(policy);
286 ewk_policy_decision_use(policy);
289 evas_object_smart_callback_add(ewk_view_,
290 "policy,newwindow,decide",
291 newwindow_decide_callback,
293 smart_callbacks_["policy,navigation,decide"] = navigation_decide_callback;
294 smart_callbacks_["policy,newwindow,decide"] = newwindow_decide_callback;
297 void WebViewImpl::InitQuotaExceededCallback() {
298 // TODO(sngn.lee): Need callback interface - OnQutaExceed
299 // check http://tizen.org/privilege/unlimitedstorage
301 // callback for database quota exceeded
302 // TODO(wy80.choi): AARCH64:
303 // Fix ewk api to use stdint types instead of longlong.
304 auto database_exceeded_callback = [](Evas_Object* view,
305 Ewk_Security_Origin* origin,
308 void* user_data) -> Eina_Bool {
309 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
310 if (self == NULL || self->listener_ == NULL)
313 auto result_handler = [view](bool result) {
314 LOGGER(DEBUG) << "database quota Permission Result : " << result;
315 ewk_view_exceeded_database_quota_reply(view, result);
317 std::stringstream url;
318 url << ewk_security_origin_protocol_get(origin)
320 << ewk_security_origin_host_get(origin)
322 << ewk_security_origin_port_get(origin);
323 self->listener_->OnQuotaExceed(
329 ewk_view_exceeded_database_quota_callback_set(
331 database_exceeded_callback,
334 // callback for indexed database quota exceeded
335 // TODO(wy80.choi): AARCH64:
336 // Fix ewk api to use stdint types instead of longlong.
337 auto indexed_db_exceeded_callback = [](Evas_Object* view,
338 Ewk_Security_Origin* origin,
340 void* user_data) -> Eina_Bool {
341 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
342 if (self == NULL || self->listener_ == NULL)
345 auto result_handler = [view](bool result) {
346 LOGGER(DEBUG) << "indexed db quota Permission Result : " << result;
347 ewk_view_exceeded_indexed_database_quota_reply(view, result);
349 std::stringstream url;
350 url << ewk_security_origin_protocol_get(origin)
352 << ewk_security_origin_host_get(origin)
354 << ewk_security_origin_port_get(origin);
355 self->listener_->OnQuotaExceed(
361 ewk_view_exceeded_indexed_database_quota_callback_set(
363 indexed_db_exceeded_callback,
366 // callback for localfile quota exceeded
367 // TODO(wy80.choi): AARCH64:
368 // Fix ewk api to use stdint types instead of longlong.
369 auto localfile_exceeded_callback = [](Evas_Object* view,
370 Ewk_Security_Origin* origin,
372 void* user_data) -> Eina_Bool {
373 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
374 if (self == NULL || self->listener_ == NULL)
377 auto result_handler = [view](bool result) {
378 LOGGER(DEBUG) << "local file quota Permission Result : " << result;
379 ewk_view_exceeded_local_file_system_quota_reply(view, result);
381 std::stringstream url;
382 url << ewk_security_origin_protocol_get(origin)
384 << ewk_security_origin_host_get(origin)
386 << ewk_security_origin_port_get(origin);
387 self->listener_->OnQuotaExceed(
393 ewk_view_exceeded_local_file_system_quota_callback_set(
395 localfile_exceeded_callback,
399 void WebViewImpl::InitIPCMessageCallback() {
401 auto wrt_message_callback = [](void* user_data,
404 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
405 Ewk_IPC_Wrt_Message_Data* msg =
406 static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
408 self->listener_->OnReceivedWrtMessage(self->view_, msg);
410 evas_object_smart_callback_add(ewk_view_,
412 wrt_message_callback,
414 smart_callbacks_["wrt,message"] = wrt_message_callback;
417 void WebViewImpl::InitOrientaionLockCallback() {
418 // Orientation lock callback
419 auto orientation_lock_callback = [](Evas_Object*,
422 void* user_data) -> Eina_Bool {
423 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
424 if (self->listener_) {
425 self->listener_->OnOrientationLock(self->view_,
427 ToNativeRotation(orientation));
431 ewk_view_orientation_lock_callback_set(ewk_view_,
432 orientation_lock_callback,
436 void WebViewImpl::InitConsoleMessageCallback() {
438 auto console_message_callback = [](void* user_data,
441 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
442 if (!self->listener_) {
445 Ewk_Console_Message* msg = static_cast<Ewk_Console_Message*>(event_info);
446 unsigned int line_number = ewk_console_message_line_get(msg);
448 std::stringstream buf;
450 buf << ewk_console_message_source_get(msg) << ":";
451 buf << line_number << ":";
453 buf << ewk_console_message_text_get(msg);
454 int level = ewk_console_message_level_get(msg);
455 self->listener_->OnConsoleMessage(buf.str(), level);
457 evas_object_smart_callback_add(ewk_view_,
459 console_message_callback,
461 smart_callbacks_["console,message"] = console_message_callback;
464 void WebViewImpl::InitCustomContextMenuCallback() {
465 auto custom_context_menu_callback = [](void* user_data,
468 Ewk_Context_Menu* contextmenu = static_cast<Ewk_Context_Menu*>(event_info);
469 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
470 bool disabled = false;
471 if (self->listener_ &&
472 self->listener_->OnContextMenuDisabled(self->view_)) {
475 int cnt = ewk_context_menu_item_count(contextmenu);
476 for (unsigned idx = cnt-1; idx > 0; --idx) {
477 auto* item = ewk_context_menu_nth_item_get(contextmenu, idx);
478 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
480 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
481 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
482 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
483 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
484 case EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_IMAGE_TO_DISK:
485 ewk_context_menu_item_remove(contextmenu, item);
489 ewk_context_menu_item_remove(contextmenu, item);
493 evas_object_smart_callback_add(ewk_view_,
494 "contextmenu,customize",
495 custom_context_menu_callback,
497 smart_callbacks_["contextmenu,customize"] = custom_context_menu_callback;
500 void WebViewImpl::InitRotationCallback() {
502 ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
503 rotation_handler_id_ = window_->AddRotationHandler(
504 std::bind(&WebViewImpl::OnRotation,
506 std::placeholders::_1));
509 void WebViewImpl::InitWindowCreateCallback() {
510 auto create_callback = [](void* user_data,
513 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
514 if (!self->listener_) {
517 WebView* new_view = new WebView(self->window_, self->context_);
518 self->listener_->OnCreatedNewWebView(self->view_, new_view);
519 *(static_cast<Evas_Object **>(event_info)) = new_view->evas_object();
522 auto close_callback = [](void* user_data,
525 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
526 if (!self->listener_) {
529 self->listener_->OnClosedWebView(self->view_);
531 evas_object_smart_callback_add(ewk_view_,
535 evas_object_smart_callback_add(ewk_view_,
540 smart_callbacks_["create,window"] = create_callback;
541 smart_callbacks_["close,window"] = close_callback;
544 void WebViewImpl::InitFullscreenCallback() {
545 auto enter_callback = [](void* user_data,
547 void* /*event_info*/) {
548 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
549 self->fullscreen_ = true;
550 self->window_->FullScreen(true);
552 auto exit_callback = [](void* user_data,
554 void* /*event_info*/) {
555 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
556 self->fullscreen_ = false;
557 self->window_->FullScreen(false);
559 evas_object_smart_callback_add(ewk_view_,
560 "fullscreen,enterfullscreen",
563 evas_object_smart_callback_add(ewk_view_,
564 "fullscreen,exitfullscreen",
567 smart_callbacks_["fullscreen,enterfullscreen"] = enter_callback;
568 smart_callbacks_["fullscreen,exitfullscreen"] = exit_callback;
571 void WebViewImpl::InitNotificationPermissionCallback() {
572 auto request_callback = [](Evas_Object*,
573 Ewk_Notification_Permission_Request* request,
575 LOGGER(DEBUG) << "Notification Permission Request";
576 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
577 if (!self->listener_) {
578 ewk_notification_permission_reply(request, EINA_FALSE);
582 ewk_notification_permission_request_suspend(request);
583 auto result_handler = [request](bool result) {
584 LOGGER(DEBUG) << "Notification Permission Result : %d" << result;
585 ewk_notification_permission_reply(request, result);
587 const Ewk_Security_Origin* ewk_origin =
588 ewk_notification_permission_request_origin_get(request);
590 std::stringstream url;
591 url << ewk_security_origin_protocol_get(ewk_origin)
593 << ewk_security_origin_host_get(ewk_origin)
595 << ewk_security_origin_port_get(ewk_origin);
596 self->listener_->OnNotificationPermissionRequest(
602 ewk_view_notification_permission_callback_set(ewk_view_,
607 void WebViewImpl::InitGeolocationPermissionCallback() {
608 auto permission_callback = [](
610 Ewk_Geolocation_Permission_Request* request,
612 LOGGER(DEBUG) << "Geolocation Permission Request";
613 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
614 if (self == NULL || self->listener_ == NULL) {
615 ewk_geolocation_permission_reply(request, EINA_FALSE);
618 ewk_geolocation_permission_request_suspend(request);
620 const Ewk_Security_Origin* ewk_origin =
621 ewk_geolocation_permission_request_origin_get(request);
622 auto result_handler = [request](bool result) {
623 LOGGER(DEBUG) << "Geolocation Permission Result : " << result;
624 ewk_geolocation_permission_reply(request, result);
627 std::stringstream url;
628 url << ewk_security_origin_protocol_get(ewk_origin)
630 << ewk_security_origin_host_get(ewk_origin)
632 << ewk_security_origin_port_get(ewk_origin);
634 self->listener_->OnGeolocationPermissionRequest(
640 ewk_view_geolocation_permission_callback_set(ewk_view_,
645 void WebViewImpl::InitAuthenticationCallback() {
646 auto auth_callback = [](void* user_data,
649 LOGGER(DEBUG) << "Authentication Request";
650 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
651 Ewk_Auth_Challenge* auth_challenge =
652 static_cast<Ewk_Auth_Challenge*>(event_info);
654 if (self == NULL || self->listener_ == NULL) {
655 ewk_auth_challenge_credential_cancel(auth_challenge);
658 auto result_handler = [auth_challenge](bool submit,
659 const std::string& id,
660 const std::string& password) {
661 LOGGER(DEBUG) << "Authentication Result : submit = " << submit;
663 ewk_auth_challenge_credential_cancel(auth_challenge);
666 ewk_auth_challenge_credential_use(auth_challenge,
670 ewk_auth_challenge_suspend(auth_challenge);
671 const char* message =
672 ewk_auth_challenge_realm_get(auth_challenge);
673 std::string url = self->GetUrl();
674 self->listener_->OnAuthenticationRequest(self->view_,
679 // "authentication,challenge"
680 evas_object_smart_callback_add(ewk_view_,
681 "authentication,challenge",
684 smart_callbacks_["authentication,challenge"] = auth_callback;
687 void WebViewImpl::InitCertificateAllowCallback() {
688 auto certi_callback = [](void* user_data,
691 WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
692 Ewk_Certificate_Policy_Decision* policy =
693 static_cast<Ewk_Certificate_Policy_Decision*>(event_info);
695 if (self == NULL || self->listener_ == NULL) {
696 ewk_certificate_policy_decision_allowed_set(policy, EINA_FALSE);
700 ewk_certificate_policy_decision_suspend(policy);
701 auto result_handler = [policy](bool allow) {
702 ewk_certificate_policy_decision_allowed_set(policy, allow);
705 auto ptr = ewk_certificate_policy_decision_url_get(policy);
706 std::string url(ptr ? ptr : "");
707 ptr = ewk_certificate_policy_decision_certificate_pem_get(policy);
708 std::string pem(ptr ? ptr : "");
709 self->listener_->OnCertificateAllowRequest(self->view_,
714 evas_object_smart_callback_add(ewk_view_,
715 "request,certificate,confirm",
718 smart_callbacks_["request,certificate,confirm"] = certi_callback;
722 std::string WebViewImpl::GetUrl() {
723 return std::string(ewk_view_url_get(ewk_view_));
726 Evas_Object* WebViewImpl::evas_object() const {
730 void WebViewImpl::OnRotation(int degree) {
731 ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
734 void WebViewImpl::OnKeyEvent(Ea_Callback_Type key_type) {
736 if (key_type == EA_CALLBACK_BACK) {
738 ewk_view_fullscreen_exit(ewk_view_);
741 if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
744 keyname = kKeyNameBack;
745 } else if (key_type == EA_CALLBACK_MORE) {
746 keyname = kKeyNameMenu;
752 listener_->OnHardwareKey(view_, keyname);
755 void WebViewImpl::SetEventListener(WebView::EventListener* listener) {
756 listener_ = listener;
759 void WebViewImpl::SetAppInfo(const std::string& app_name,
760 const std::string& version) {
761 std::string ua = app_name + "/" + version;
762 ewk_view_application_name_for_user_agent_set(ewk_view_, ua.c_str());
764 bool WebViewImpl::SetUserAgent(const std::string& user_agent) {
765 return ewk_view_user_agent_set(ewk_view_, user_agent.c_str());