Fix prevent alarms
[platform/framework/web/crosswalk-tizen.git] / runtime / browser / web_view_impl.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include "runtime/browser/web_view_impl.h"
19
20 #include <ewk_chromium.h>
21 #include <functional>
22 #include <sstream>
23
24 #include "common/file_utils.h"
25 #include "common/logger.h"
26 #include "common/profiler.h"
27 #include "runtime/browser/native_window.h"
28
29 namespace runtime {
30
31 namespace {
32
33 const char* kKeyNameBack = "back";
34 const char* kKeyNameMenu = "menu";
35 const char* kDefaultEncoding = "UTF-8";
36 const char* kSmartClassUserDataKey = "__SC_USERDATA__";
37
38 static int ToWebRotation(int r) {
39   switch (r) {
40     case 90:
41       return -90;
42     case 270:
43       return 90;
44   }
45   return r;
46 }
47
48 static NativeWindow::ScreenOrientation ToNativeRotation(int r) {
49   if (r ==
50       (EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY
51        | EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY
52        | EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY
53        | EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY)) {
54     return NativeWindow::ScreenOrientation::ANY;
55   } else if (r ==
56       (EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY
57        | EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY)) {
58     return NativeWindow::ScreenOrientation::NATURAL;
59   } else if (r & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
60     return NativeWindow::ScreenOrientation::PORTRAIT_PRIMARY;
61   } else if (r & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
62     return NativeWindow::ScreenOrientation::PORTRAIT_SECONDARY;
63   } else if (r & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
64     return NativeWindow::ScreenOrientation::LANDSCAPE_PRIMARY;
65   } else {
66     return NativeWindow::ScreenOrientation::LANDSCAPE_SECONDARY;
67   }
68 }
69
70 }  // namespace
71
72 WebViewImpl::WebViewImpl(WebView* view,
73                          NativeWindow* window,
74                          Ewk_Context* context)
75     : window_(window),
76       context_(context),
77       ewk_view_(NULL),
78       listener_(NULL),
79       rotation_handler_id_(0),
80       view_(view),
81       fullscreen_(false),
82       evas_smart_class_(NULL),
83       internal_popup_opened_(false) {
84   Initialize();
85 }
86
87 WebViewImpl::~WebViewImpl() {
88   if (internal_popup_opened_) {
89     ewk_view_javascript_alert_reply(ewk_view_);
90   }
91   Deinitialize();
92   evas_object_del(ewk_view_);
93   if (evas_smart_class_ != NULL)
94     evas_smart_free(evas_smart_class_);
95 }
96
97 void WebViewImpl::LoadUrl(const std::string& url, const std::string& mime) {
98   SCOPE_PROFILE();
99   if (!mime.empty()) {
100     mime_ = mime;
101     auto mime_override_cb = [](const char* url, const char* mime,
102                                char** new_mime, void* data) -> Eina_Bool{
103       WebViewImpl* view = static_cast<WebViewImpl*>(data);
104       if (view != nullptr &&
105           common::utils::BaseName(url) ==
106             common::utils::BaseName(view->GetUrl())) {
107         *new_mime = strdup(view->mime().c_str());
108         LOGGER(DEBUG) << "ewk's new_mime: " << *new_mime;
109         return EINA_TRUE;
110       }
111       return EINA_FALSE;
112     };
113     ewk_context_mime_override_callback_set(context_, mime_override_cb, this);
114   }
115   ewk_view_url_set(ewk_view_, url.c_str());
116 }
117
118 void WebViewImpl::Suspend() {
119   // suspend webview
120   ewk_view_suspend(ewk_view_);
121 }
122
123 void WebViewImpl::Resume() {
124   // resume webview
125   ewk_view_resume(ewk_view_);
126 }
127
128 void WebViewImpl::Reload() {
129   ewk_view_reload(ewk_view_);
130 }
131
132 void WebViewImpl::SetVisibility(bool show) {
133   ewk_view_visibility_set(ewk_view_, show ? EINA_TRUE : EINA_FALSE);
134 }
135
136
137 bool WebViewImpl::EvalJavascript(const std::string& script) {
138   return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
139 }
140
141 void WebViewImpl::Initialize() {
142   ewk_smart_class_ = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("WebView");
143   ewk_view_smart_class_set(&ewk_smart_class_);
144   ewk_smart_class_.orientation_lock = [](Ewk_View_Smart_Data *sd,
145                                          int orientation) {
146     WebViewImpl* self = static_cast<WebViewImpl*>(
147         evas_object_data_get(sd->self, kSmartClassUserDataKey));
148     if (self == NULL || self->listener_ == NULL)
149       return EINA_FALSE;
150     self->listener_->OnOrientationLock(self->view_,
151                                        true,
152                                        ToNativeRotation(orientation));
153     return EINA_TRUE;
154   };
155
156   ewk_smart_class_.orientation_unlock = [](Ewk_View_Smart_Data *sd) {
157     WebViewImpl* self = static_cast<WebViewImpl*>(
158         evas_object_data_get(sd->self, kSmartClassUserDataKey));
159     if (self == NULL || self->listener_ == NULL)
160       return;
161     self->listener_->OnOrientationLock(
162         self->view_,
163         false,
164         NativeWindow::ScreenOrientation::PORTRAIT_PRIMARY);
165   };
166
167   if (evas_smart_class_ != NULL)
168     evas_smart_free(evas_smart_class_);
169   evas_smart_class_ = evas_smart_class_new(&ewk_smart_class_.sc);
170   if (evas_smart_class_ == NULL) {
171     LOGGER(ERROR) << "Can't create evas smart class";
172     return;
173   }
174
175   Ewk_Page_Group* page_group = ewk_page_group_create("");
176   ewk_view_ = ewk_view_smart_add(evas_object_evas_get(window_->evas_object()),
177                                  evas_smart_class_,
178                                  context_,
179                                  page_group);
180   evas_object_data_set(ewk_view_, kSmartClassUserDataKey, this);
181
182   InitKeyCallback();
183   InitLoaderCallback();
184   InitPolicyDecideCallback();
185   InitQuotaExceededCallback();
186   InitIPCMessageCallback();
187   InitConsoleMessageCallback();
188   InitCustomContextMenuCallback();
189   InitRotationCallback();
190   InitWindowCreateCallback();
191   InitFullscreenCallback();
192   InitNotificationPermissionCallback();
193   InitGeolocationPermissionCallback();
194   InitAuthenticationCallback();
195   InitCertificateAllowCallback();
196   InitPopupWaitCallback();
197   InitUsermediaCallback();
198
199   Ewk_Settings* settings = ewk_view_settings_get(ewk_view_);
200   ewk_settings_scripts_can_open_windows_set(settings, EINA_TRUE);
201   ewk_settings_default_text_encoding_name_set(settings, kDefaultEncoding);
202
203   // TODO(sngn.lee): "protocolhandler,registration,requested"
204   //                  custom protocol handler
205
206   // Show webview
207   evas_object_show(ewk_view_);
208 }
209
210 void WebViewImpl::Deinitialize() {
211   auto it = smart_callbacks_.begin();
212   for ( ; it != smart_callbacks_.end(); ++it) {
213     evas_object_smart_callback_del(
214         ewk_view_,
215         it->first.c_str(),
216         it->second);
217   }
218   eext_object_event_callback_del(ewk_view_,
219                                EEXT_CALLBACK_BACK,
220                                smart_callbacks_["key_callback"]);
221   ewk_view_exceeded_database_quota_callback_set(
222       ewk_view_,
223       NULL,
224       NULL);
225   ewk_view_exceeded_indexed_database_quota_callback_set(
226       ewk_view_,
227       NULL,
228       NULL);
229   ewk_view_exceeded_local_file_system_quota_callback_set(
230       ewk_view_,
231       NULL,
232       NULL);
233   ewk_view_notification_permission_callback_set(
234       ewk_view_,
235       NULL,
236       NULL);
237   ewk_view_geolocation_permission_callback_set(
238       ewk_view_,
239       NULL,
240       NULL);
241   ewk_view_user_media_permission_callback_set(
242       ewk_view_,
243       NULL,
244       NULL);
245   window_->RemoveRotationHandler(rotation_handler_id_);
246 }
247
248 void WebViewImpl::InitKeyCallback() {
249   auto key_callback = [](void* user_data,
250                          Evas_Object* /*obj*/,
251                          void* event_info) -> void {
252     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
253     Eext_Callback_Type key = static_cast<Eext_Callback_Type>(
254       reinterpret_cast<long long>(event_info));  // NOLINT
255     self->OnKeyEvent(key);
256   };
257   eext_object_event_callback_add(ewk_view_,
258                                EEXT_CALLBACK_BACK,
259                                key_callback,
260                                this);
261   eext_object_event_callback_add(ewk_view_,
262                                EEXT_CALLBACK_MORE,
263                                key_callback,
264                                this);
265   smart_callbacks_["key_callback"] = key_callback;
266 }
267
268 void WebViewImpl::InitLoaderCallback() {
269   // load statred callback
270   auto loadstart_callback = [](void* user_data,
271                                Evas_Object* /*obj*/,
272                                void*) {
273     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
274     if (self->listener_)
275       self->listener_->OnLoadStart(self->view_);
276   };
277   evas_object_smart_callback_add(ewk_view_,
278                                  "load,started",
279                                  loadstart_callback,
280                                  this);
281   // load finished callback
282   auto loadfinished_callback = [](void* user_data,
283                                   Evas_Object*,
284                                   void*) {
285     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
286     if (self->listener_)
287       self->listener_->OnLoadFinished(self->view_);
288   };
289   evas_object_smart_callback_add(ewk_view_,
290                                  "load,finished",
291                                  loadfinished_callback,
292                                  this);
293
294   // load progress callback
295   auto loadprogress_callback = [](void* user_data,
296                                   Evas_Object*,
297                                   void* event_info) {
298     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
299     double* progress = static_cast<double*>(event_info);
300     if (self->listener_)
301       self->listener_->OnLoadProgress(self->view_, *progress);
302   };
303   evas_object_smart_callback_add(ewk_view_,
304                                  "load,progress",
305                                  loadprogress_callback,
306                                  this);
307   // rendered callback
308   auto rendered_callback = [](void* user_data,
309                               Evas_Object*,
310                               void*) {
311     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
312     if (self->listener_)
313       self->listener_->OnRendered(self->view_);
314   };
315   evas_object_smart_callback_add(ewk_view_,
316                                  "frame,rendered",
317                                  rendered_callback,
318                                  this);
319   smart_callbacks_["load,started"] = loadstart_callback;
320   smart_callbacks_["load,finished"] = loadfinished_callback;
321   smart_callbacks_["load,progress"] = loadprogress_callback;
322   smart_callbacks_["frame,rendered"] = rendered_callback;
323 }
324
325 void WebViewImpl::InitPolicyDecideCallback() {
326   // "policy,navigation,decide"
327   auto navigation_decide_callback = [](void* user_data,
328                                        Evas_Object*,
329                                        void* event_info) {
330     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
331     Ewk_Policy_Decision* policy =
332             static_cast<Ewk_Policy_Decision*>(event_info);
333     const char* url = ewk_policy_decision_url_get(policy);
334
335     if (self->listener_) {
336       if (self->listener_->OnDidNavigation(self->view_, url))
337         ewk_policy_decision_use(policy);
338       else
339         ewk_policy_decision_ignore(policy);
340     } else {
341       ewk_policy_decision_use(policy);
342     }
343   };
344   evas_object_smart_callback_add(ewk_view_,
345                                  "policy,navigation,decide",
346                                  navigation_decide_callback,
347                                  this);
348
349   // policy,newwindow,decide
350   auto newwindow_decide_callback = [](void* user_data,
351                                       Evas_Object*,
352                                       void* event_info) {
353     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
354     Ewk_Policy_Decision* policy =
355             static_cast<Ewk_Policy_Decision*>(event_info);
356
357     const char* url = ewk_policy_decision_url_get(policy);
358
359     if (self->listener_) {
360       if (self->listener_->OnDidNavigation(self->view_, url) &&
361          self->listener_->OnDidOpenWindow(self->view_, url)) {
362          ewk_policy_decision_use(policy);
363       } else {
364         ewk_policy_decision_ignore(policy);
365       }
366     } else {
367       ewk_policy_decision_use(policy);
368     }
369   };
370   evas_object_smart_callback_add(ewk_view_,
371                                  "policy,newwindow,decide",
372                                  newwindow_decide_callback,
373                                  this);
374   smart_callbacks_["policy,navigation,decide"] = navigation_decide_callback;
375   smart_callbacks_["policy,newwindow,decide"] = newwindow_decide_callback;
376 }
377
378 void WebViewImpl::InitQuotaExceededCallback() {
379   // TODO(sngn.lee): Need callback interface - OnQutaExceed
380   // check http://tizen.org/privilege/unlimitedstorage
381
382   // callback for database quota exceeded
383   auto database_exceeded_callback = [](Evas_Object* view,
384                                        Ewk_Security_Origin* origin,
385                                        const char*,
386                                        unsigned long long, // NOLINT
387                                        void* user_data) -> Eina_Bool {
388     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
389     if (self == NULL || self->listener_ == NULL)
390       return EINA_TRUE;
391
392     auto result_handler = [view](bool result) {
393       LOGGER(DEBUG) << "database quota Permission Result : " << result;
394       ewk_view_exceeded_database_quota_reply(view, result);
395     };
396     std::stringstream url;
397     url << ewk_security_origin_protocol_get(origin)
398         << "://"
399         << ewk_security_origin_host_get(origin)
400         << ":"
401         << ewk_security_origin_port_get(origin);
402     self->listener_->OnQuotaExceed(
403         self->view_,
404         url.str(),
405         result_handler);
406     return EINA_TRUE;
407   };
408   ewk_view_exceeded_database_quota_callback_set(
409     ewk_view_,
410     database_exceeded_callback,
411     this);
412
413   // callback for indexed database quota exceeded
414   auto indexed_db_exceeded_callback = [](Evas_Object* view,
415                                        Ewk_Security_Origin* origin,
416                                        long long, // NOLINT
417                                        void* user_data) -> Eina_Bool {
418     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
419     if (self == NULL || self->listener_ == NULL)
420       return EINA_TRUE;
421
422     auto result_handler = [view](bool result) {
423       LOGGER(DEBUG) << "indexed db quota Permission Result : " << result;
424       ewk_view_exceeded_indexed_database_quota_reply(view, result);
425     };
426     std::stringstream url;
427     url << ewk_security_origin_protocol_get(origin)
428         << "://"
429         << ewk_security_origin_host_get(origin)
430         << ":"
431         << ewk_security_origin_port_get(origin);
432     self->listener_->OnQuotaExceed(
433         self->view_,
434         url.str(),
435         result_handler);
436     return EINA_TRUE;
437   };
438   ewk_view_exceeded_indexed_database_quota_callback_set(
439     ewk_view_,
440     indexed_db_exceeded_callback,
441     this);
442
443   // callback for localfile quota exceeded
444   auto localfile_exceeded_callback = [](Evas_Object* view,
445                                        Ewk_Security_Origin* origin,
446                                        long long, // NOLINT
447                                        void* user_data) -> Eina_Bool {
448     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
449     if (self == NULL || self->listener_ == NULL)
450       return EINA_TRUE;
451
452     auto result_handler = [view](bool result) {
453       LOGGER(DEBUG) << "local file quota Permission Result : " << result;
454       ewk_view_exceeded_local_file_system_quota_reply(view, result);
455     };
456     std::stringstream url;
457     url << ewk_security_origin_protocol_get(origin)
458         << "://"
459         << ewk_security_origin_host_get(origin)
460         << ":"
461         << ewk_security_origin_port_get(origin);
462     self->listener_->OnQuotaExceed(
463         self->view_,
464         url.str(),
465         result_handler);
466     return EINA_TRUE;
467   };
468   ewk_view_exceeded_local_file_system_quota_callback_set(
469     ewk_view_,
470     localfile_exceeded_callback,
471     this);
472 }
473
474 void WebViewImpl::InitIPCMessageCallback() {
475   // wrt,message
476   auto wrt_message_callback = [](void* user_data,
477                                  Evas_Object*,
478                                  void* event_info) {
479     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
480     Ewk_IPC_Wrt_Message_Data* msg =
481         static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
482     if (self->listener_)
483       self->listener_->OnReceivedWrtMessage(self->view_, msg);
484   };
485   evas_object_smart_callback_add(ewk_view_,
486                                  "wrt,message",
487                                  wrt_message_callback,
488                                  this);
489   smart_callbacks_["wrt,message"] = wrt_message_callback;
490 }
491
492 void WebViewImpl::InitConsoleMessageCallback() {
493   // console log
494   auto console_message_callback = [](void* user_data,
495                                  Evas_Object*,
496                                  void* event_info) {
497     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
498     if (!self->listener_) {
499       return;
500     }
501     Ewk_Console_Message* msg = static_cast<Ewk_Console_Message*>(event_info);
502     unsigned int line_number = ewk_console_message_line_get(msg);
503
504     std::stringstream buf;
505     if (line_number) {
506         buf << common::utils::BaseName(ewk_console_message_source_get(msg))
507             << ":" << line_number << ": ";
508     }
509     buf << ewk_console_message_text_get(msg);
510     int level = ewk_console_message_level_get(msg);
511     self->listener_->OnConsoleMessage(buf.str(), level);
512   };
513   evas_object_smart_callback_add(ewk_view_,
514                                  "console,message",
515                                  console_message_callback,
516                                  this);
517   smart_callbacks_["console,message"] = console_message_callback;
518 }
519
520 void WebViewImpl::InitCustomContextMenuCallback() {
521   auto custom_context_menu_callback = [](void* user_data,
522                                          Evas_Object*,
523                                          void* event_info) {
524     Ewk_Context_Menu* contextmenu = static_cast<Ewk_Context_Menu*>(event_info);
525     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
526     bool disabled = false;
527     if (self->listener_ &&
528         self->listener_->OnContextMenuDisabled(self->view_)) {
529       disabled = true;
530     }
531     int cnt = ewk_context_menu_item_count(contextmenu);
532     for (int idx = cnt-1; idx >= 0; --idx) {
533       auto* item = ewk_context_menu_nth_item_get(contextmenu, idx);
534       Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
535       switch (tag) {
536         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
537         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
538         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
539         case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
540         case EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_IMAGE_TO_DISK:
541           ewk_context_menu_item_remove(contextmenu, item);
542           break;
543         default:
544           if (disabled)
545             ewk_context_menu_item_remove(contextmenu, item);
546       }
547     }
548   };
549   evas_object_smart_callback_add(ewk_view_,
550                                  "contextmenu,customize",
551                                  custom_context_menu_callback,
552                                  this);
553   smart_callbacks_["contextmenu,customize"] = custom_context_menu_callback;
554 }
555
556 void WebViewImpl::InitRotationCallback() {
557   // rotation support
558   ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
559   rotation_handler_id_ = window_->AddRotationHandler(
560                                   std::bind(&WebViewImpl::OnRotation,
561                                   this,
562                                   std::placeholders::_1));
563 }
564
565 void WebViewImpl::InitWindowCreateCallback() {
566   auto create_callback = [](void* user_data,
567                             Evas_Object*,
568                             void* event_info) {
569     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
570     if (!self->listener_) {
571       return;
572     }
573     WebView* new_view = new WebView(self->window_, self->context_);
574     self->listener_->OnCreatedNewWebView(self->view_, new_view);
575     *(static_cast<Evas_Object **>(event_info)) = new_view->evas_object();
576   };
577
578   auto close_callback = [](void* user_data,
579                             Evas_Object*,
580                             void*) {
581     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
582     if (!self->listener_) {
583       return;
584     }
585     self->listener_->OnClosedWebView(self->view_);
586   };
587   evas_object_smart_callback_add(ewk_view_,
588                                  "create,window",
589                                  create_callback,
590                                  this);
591   evas_object_smart_callback_add(ewk_view_,
592                                  "close,window",
593                                  close_callback,
594                                  this);
595
596   smart_callbacks_["create,window"] = create_callback;
597   smart_callbacks_["close,window"] = close_callback;
598 }
599
600 void WebViewImpl::InitFullscreenCallback() {
601   auto enter_callback = [](void* user_data,
602                             Evas_Object*,
603                             void* /*event_info*/) {
604     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
605     self->fullscreen_ = true;
606     self->window_->FullScreen(true);
607   };
608   auto exit_callback =  [](void* user_data,
609                             Evas_Object*,
610                             void* /*event_info*/) {
611     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
612     self->fullscreen_ = false;
613     self->window_->FullScreen(false);
614   };
615   evas_object_smart_callback_add(ewk_view_,
616                                  "fullscreen,enterfullscreen",
617                                  enter_callback,
618                                  this);
619   evas_object_smart_callback_add(ewk_view_,
620                                  "fullscreen,exitfullscreen",
621                                  exit_callback,
622                                  this);
623   smart_callbacks_["fullscreen,enterfullscreen"] = enter_callback;
624   smart_callbacks_["fullscreen,exitfullscreen"] = exit_callback;
625 }
626
627 void WebViewImpl::InitNotificationPermissionCallback() {
628   auto request_callback = [](Evas_Object*,
629                              Ewk_Notification_Permission_Request* request,
630                              void* user_data) {
631     LOGGER(DEBUG) << "Notification Permission Request";
632     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
633     if (!self->listener_) {
634       ewk_notification_permission_reply(request, EINA_FALSE);
635       return EINA_TRUE;
636     }
637
638     ewk_notification_permission_request_suspend(request);
639     auto result_handler = [request](bool result) {
640       LOGGER(DEBUG) << "Notification Permission Result : %d" << result;
641       ewk_notification_permission_reply(request, result);
642     };
643     const Ewk_Security_Origin* ewk_origin =
644         ewk_notification_permission_request_origin_get(request);
645
646     std::stringstream url;
647     url << ewk_security_origin_protocol_get(ewk_origin)
648         << "://"
649         << ewk_security_origin_host_get(ewk_origin)
650         << ":"
651         << ewk_security_origin_port_get(ewk_origin);
652     self->listener_->OnNotificationPermissionRequest(
653         self->view_,
654         url.str(),
655         result_handler);
656     return EINA_TRUE;
657   };
658   ewk_view_notification_permission_callback_set(ewk_view_,
659                                                 request_callback,
660                                                 this);
661 }
662
663 void WebViewImpl::InitGeolocationPermissionCallback() {
664   auto permission_callback = [](
665       Evas_Object*,
666       Ewk_Geolocation_Permission_Request* request,
667       void* user_data) {
668     LOGGER(DEBUG) << "Geolocation Permission Request";
669     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
670     if (self == NULL || self->listener_ == NULL) {
671       ewk_geolocation_permission_reply(request, EINA_FALSE);
672       return EINA_TRUE;
673     }
674     ewk_geolocation_permission_request_suspend(request);
675
676     const Ewk_Security_Origin* ewk_origin =
677         ewk_geolocation_permission_request_origin_get(request);
678     auto result_handler = [request](bool result) {
679       LOGGER(DEBUG) << "Geolocation Permission Result : " << result;
680       ewk_geolocation_permission_reply(request, result);
681     };
682
683     std::stringstream url;
684     url << ewk_security_origin_protocol_get(ewk_origin)
685         << "://"
686         << ewk_security_origin_host_get(ewk_origin)
687         << ":"
688         << ewk_security_origin_port_get(ewk_origin);
689
690     self->listener_->OnGeolocationPermissionRequest(
691         self->view_,
692         url.str(),
693         result_handler);
694     return EINA_TRUE;
695   };
696   ewk_view_geolocation_permission_callback_set(ewk_view_,
697                                                permission_callback,
698                                                this);
699 }
700
701 void WebViewImpl::InitAuthenticationCallback() {
702   auto auth_callback = [](void* user_data,
703                           Evas_Object*,
704                           void* event_info) {
705     LOGGER(DEBUG) << "Authentication Request";
706     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
707     Ewk_Auth_Challenge* auth_challenge =
708         static_cast<Ewk_Auth_Challenge*>(event_info);
709
710     if (self == NULL || self->listener_ == NULL) {
711       ewk_auth_challenge_credential_cancel(auth_challenge);
712       return;
713     }
714     auto result_handler = [auth_challenge](bool submit,
715                                     const std::string& id,
716                                     const std::string& password) {
717       LOGGER(DEBUG) << "Authentication Result : submit = " << submit;
718       if (!submit) {
719         ewk_auth_challenge_credential_cancel(auth_challenge);
720         return;
721       }
722       ewk_auth_challenge_credential_use(auth_challenge,
723                                         id.c_str(),
724                                         password.c_str());
725     };
726     ewk_auth_challenge_suspend(auth_challenge);
727     const char* message =
728         ewk_auth_challenge_realm_get(auth_challenge);
729     std::string url = self->GetUrl();
730     self->listener_->OnAuthenticationRequest(self->view_,
731                                              url,
732                                              message,
733                                              result_handler);
734   };
735   // "authentication,challenge"
736   evas_object_smart_callback_add(ewk_view_,
737                                  "authentication,challenge",
738                                  auth_callback,
739                                  this);
740   smart_callbacks_["authentication,challenge"] = auth_callback;
741 }
742
743 void WebViewImpl::InitCertificateAllowCallback() {
744   auto certi_callback = [](void* user_data,
745                            Evas_Object*,
746                            void* event_info) {
747     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
748     Ewk_Certificate_Policy_Decision* policy =
749       static_cast<Ewk_Certificate_Policy_Decision*>(event_info);
750
751     if (self == NULL || self->listener_ == NULL) {
752       ewk_certificate_policy_decision_allowed_set(policy, EINA_FALSE);
753       return;
754     }
755
756     ewk_certificate_policy_decision_suspend(policy);
757     auto result_handler = [policy](bool allow) {
758       ewk_certificate_policy_decision_allowed_set(policy, allow);
759     };
760
761     auto ptr = ewk_certificate_policy_decision_url_get(policy);
762     std::string url(ptr ? ptr : "");
763     ptr = ewk_certificate_policy_decision_certificate_pem_get(policy);
764     std::string pem(ptr ? ptr : "");
765     self->listener_->OnCertificateAllowRequest(self->view_,
766                                                url,
767                                                pem,
768                                                result_handler);
769   };
770   evas_object_smart_callback_add(ewk_view_,
771                                  "request,certificate,confirm",
772                                  certi_callback,
773                                  this);
774   smart_callbacks_["request,certificate,confirm"] = certi_callback;
775 }
776
777 void WebViewImpl::InitPopupWaitCallback() {
778   evas_object_smart_callback_add(ewk_view_,
779       "popup,reply,wait,start",
780       [](void* user_data, Evas_Object* /*obj*/, void*) {
781         WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
782         self->internal_popup_opened_ = true;
783       }, this);
784   evas_object_smart_callback_add(ewk_view_,
785       "popup,reply,wait,finish",
786       [](void* user_data, Evas_Object* /*obj*/, void*) {
787         WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
788         self->internal_popup_opened_ = false;
789       }, this);
790 }
791
792 void WebViewImpl::InitUsermediaCallback() {
793   auto callback = [](Evas_Object*,
794                      Ewk_User_Media_Permission_Request* request,
795                      void* user_data) {
796     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
797     if (self == NULL || self->listener_ == NULL) {
798       ewk_user_media_permission_reply(request, EINA_FALSE);
799       return EINA_TRUE;
800     }
801
802     ewk_user_media_permission_request_suspend(request);
803     const Ewk_Security_Origin* origin =
804         ewk_user_media_permission_request_origin_get(request);
805     std::stringstream url;
806     url << ewk_security_origin_protocol_get(origin)
807         << "://"
808         << ewk_security_origin_host_get(origin)
809         << ":"
810         << ewk_security_origin_port_get(origin);
811
812     auto result_handler = [request](bool result) {
813       LOGGER(DEBUG) << "Getusermedia Permission Result : " << result;
814       ewk_user_media_permission_reply(request, result);
815     };
816     std::string test = url.str();
817     self->listener_->OnUsermediaPermissionRequest(self->view_,
818                                                   url.str(),
819                                                   result_handler);
820     return EINA_TRUE;
821   };
822   ewk_view_user_media_permission_callback_set(ewk_view_, callback, this);
823 }
824
825 std::string WebViewImpl::GetUrl() {
826   return std::string(ewk_view_url_get(ewk_view_));
827 }
828
829 Evas_Object* WebViewImpl::evas_object() const {
830   return ewk_view_;
831 }
832
833 void WebViewImpl::OnRotation(int degree) {
834   ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
835 }
836
837 void WebViewImpl::OnKeyEvent(Eext_Callback_Type key_type) {
838   std::string keyname;
839   if (key_type == EEXT_CALLBACK_BACK) {
840     if (fullscreen_) {
841       ewk_view_fullscreen_exit(ewk_view_);
842       return;
843     }
844     if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
845       return;
846     }
847     keyname = kKeyNameBack;
848   } else if (key_type == EEXT_CALLBACK_MORE) {
849     keyname = kKeyNameMenu;
850   } else {
851     return;
852   }
853
854   if (listener_)
855     listener_->OnHardwareKey(view_, keyname);
856 }
857
858 void WebViewImpl::SetEventListener(WebView::EventListener* listener) {
859   listener_ = listener;
860 }
861
862 void WebViewImpl::SetAppInfo(const std::string& app_name,
863                              const std::string& version) {
864   std::string ua = app_name + "/" + version;
865   ewk_view_application_name_for_user_agent_set(ewk_view_, ua.c_str());
866 }
867 bool WebViewImpl::SetUserAgent(const std::string& user_agent) {
868   return ewk_view_user_agent_set(ewk_view_, user_agent.c_str());
869 }
870
871 void WebViewImpl::SetCSPRule(const std::string& rule, bool report_only) {
872   ewk_view_content_security_policy_set(
873       ewk_view_,
874       rule.c_str(),
875       report_only ? EWK_REPORT_ONLY : EWK_ENFORCE_POLICY);
876 }
877
878 void WebViewImpl::SetDefaultEncoding(const std::string& encoding) {
879   if (ewk_settings_is_encoding_valid(encoding.c_str())) {
880     Ewk_Settings* settings = ewk_view_settings_get(ewk_view_);
881     ewk_settings_default_text_encoding_name_set(settings, encoding.c_str());
882   }
883 }
884
885 }  // namespace runtime