2c09fa65f3536c6fa054366ae847e832a7c24c99
[platform/framework/web/crosswalk-tizen.git] / src / runtime / web_view_impl.cc
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.
4
5 #include "runtime/web_view_impl.h"
6
7 #include <ewk_chromium.h>
8 #include <functional>
9 #include <sstream>
10
11 #include "runtime/native_window.h"
12 #include "common/logger.h"
13
14 namespace wrt {
15
16 namespace {
17 // TODO(sngn.lee) : It should be declare in common header
18 const char* kKeyNameBack = "back";
19 const char* kKeyNameMenu = "menu";
20
21 static int ToWebRotation(int r) {
22   switch (r) {
23     case 90:
24       return -90;
25     case 270:
26       return 90;
27   }
28   return r;
29 }
30
31 static int ToNativeRotation(int r) {
32   switch (r) {
33     case -90:
34       return 90;
35     case 90:
36       return 270;
37   }
38   return r;
39 }
40
41 }  // namespace
42
43 WebViewImpl::WebViewImpl(WebView* view,
44                          NativeWindow* window,
45                          Ewk_Context* context)
46     : window_(window),
47       context_(context),
48       ewk_view_(NULL),
49       listener_(NULL),
50       view_(view),
51       fullscreen_(false) {
52   Initialize();
53 }
54
55 WebViewImpl::~WebViewImpl() {
56   Deinitialize();
57   evas_object_del(ewk_view_);
58 }
59
60 void WebViewImpl::LoadUrl(const std::string& url) {
61   ewk_view_url_set(ewk_view_, url.c_str());
62 }
63
64 void WebViewImpl::Suspend() {
65   // suspend webview
66   ewk_view_suspend(ewk_view_);
67 }
68
69 void WebViewImpl::Resume() {
70   // resume webview
71   ewk_view_resume(ewk_view_);
72 }
73
74 void WebViewImpl::Reload() {
75   ewk_view_reload(ewk_view_);
76 }
77
78 void WebViewImpl::SetVisibility(bool show) {
79   ewk_view_visibility_set(ewk_view_, show ? EINA_TRUE : EINA_FALSE);
80 }
81
82
83 bool WebViewImpl::EvalJavascript(const std::string& script) {
84   return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
85 }
86
87 void WebViewImpl::Initialize() {
88   ewk_view_ = ewk_view_add_with_context(window_->evas_object(), context_);
89
90   InitKeyCallback();
91   InitLoaderCallback();
92   InitPolicyDecideCallback();
93   InitQuotaExceededCallback();
94   InitIPCMessageCallback();
95   InitOrientaionLockCallback();
96   InitConsoleMessageCallback();
97   InitCustomContextMenuCallback();
98   InitRotationCallback();
99   InitWindowCreateCallback();
100   InitFullscreenCallback();
101   InitNotificationPermissionCallback();
102   InitGeolocationPermissionCallback();
103   InitAuthenticationCallback();
104   InitCertificateAllowCallback();
105
106   // TODO(sngn.lee): "notification,show"
107   // TODO(sngn.lee): "notification,cancel"
108   // TODO(sngn.lee): "protocolhandler,registration,requested"
109   //                  custom protocol handler
110   // TODO(sngn.lee): ewk_view_user_media_permission_callback_set
111
112   // Show webview
113   evas_object_show(ewk_view_);
114 }
115
116 void WebViewImpl::Deinitialize() {
117   auto it = smart_callbacks_.begin();
118   for ( ; it != smart_callbacks_.end(); ++it) {
119     evas_object_smart_callback_del(
120         ewk_view_,
121         it->first.c_str(),
122         it->second);
123   }
124   ea_object_event_callback_del(ewk_view_,
125                                EA_CALLBACK_BACK,
126                                smart_callbacks_["key_callback"]);
127   ewk_view_exceeded_database_quota_callback_set(
128       ewk_view_,
129       NULL,
130       NULL);
131   ewk_view_exceeded_indexed_database_quota_callback_set(
132       ewk_view_,
133       NULL,
134       NULL);
135   ewk_view_exceeded_local_file_system_quota_callback_set(
136       ewk_view_,
137       NULL,
138       NULL);
139   ewk_view_orientation_lock_callback_set(
140       ewk_view_,
141       NULL,
142       NULL);
143   ewk_view_notification_permission_callback_set(
144       ewk_view_,
145       NULL,
146       NULL);
147   ewk_view_geolocation_permission_callback_set(
148       ewk_view_,
149       NULL,
150       NULL);
151   window_->RemoveRotationHandler(rotation_handler_id_);
152 }
153
154 void WebViewImpl::InitKeyCallback() {
155   auto key_callback = [](void* user_data,
156                          Evas_Object* /*obj*/,
157                          void* event_info) -> void {
158     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
159     Ea_Callback_Type key = static_cast<Ea_Callback_Type>(
160                               *static_cast<int*>(event_info));
161     self->OnKeyEvent(key);
162   };
163   ea_object_event_callback_add(ewk_view_,
164                                EA_CALLBACK_BACK,
165                                key_callback,
166                                view_);
167   ea_object_event_callback_add(ewk_view_,
168                                EA_CALLBACK_MORE,
169                                key_callback,
170                                view_);
171   smart_callbacks_["key_callback"] = key_callback;
172 }
173
174 void WebViewImpl::InitLoaderCallback() {
175   // load statred callback
176   auto loadstart_callback = [](void* user_data,
177                                Evas_Object* /*obj*/,
178                                void*) {
179     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
180     if (self->listener_)
181       self->listener_->OnLoadStart(self->view_);
182   };
183   evas_object_smart_callback_add(ewk_view_,
184                                  "load,started",
185                                  loadstart_callback,
186                                  this);
187   // load finished callback
188   auto loadfinished_callback = [](void* user_data,
189                                   Evas_Object*,
190                                   void*) {
191     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
192     if (self->listener_)
193       self->listener_->OnLoadFinished(self->view_);
194   };
195   evas_object_smart_callback_add(ewk_view_,
196                                  "load,finished",
197                                  loadfinished_callback,
198                                  this);
199
200   // load progress callback
201   auto loadprogress_callback = [](void* user_data,
202                                   Evas_Object*,
203                                   void* event_info) {
204     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
205     double* progress = static_cast<double*>(event_info);
206     if (self->listener_)
207       self->listener_->OnLoadProgress(self->view_, *progress);
208   };
209   evas_object_smart_callback_add(ewk_view_,
210                                  "load,progress",
211                                  loadprogress_callback,
212                                  this);
213   // rendered callback
214   auto rendered_callback = [](void* user_data,
215                               Evas_Object*,
216                               void*) {
217     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
218     if (self->listener_)
219       self->listener_->OnRendered(self->view_);
220   };
221   evas_object_smart_callback_add(ewk_view_,
222                                  "frame,rendered",
223                                  rendered_callback,
224                                  this);
225   smart_callbacks_["load,started"] = loadstart_callback;
226   smart_callbacks_["load,finished"] = loadfinished_callback;
227   smart_callbacks_["load,progress"] = loadprogress_callback;
228   smart_callbacks_["frame,rendered"] = rendered_callback;
229 }
230
231 void WebViewImpl::InitPolicyDecideCallback() {
232   // "policy,navigation,decide"
233   auto navigation_decide_callback = [](void* user_data,
234                                        Evas_Object*,
235                                        void* event_info) {
236     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
237     Ewk_Policy_Decision* policy =
238             static_cast<Ewk_Policy_Decision*>(event_info);
239     const char* url = ewk_policy_decision_url_get(policy);
240
241     if (self->listener_) {
242       if (self->listener_->OnDidNavigation(self->view_, url))
243         ewk_policy_decision_use(policy);
244       else
245         ewk_policy_decision_ignore(policy);
246     } else {
247       ewk_policy_decision_use(policy);
248     }
249   };
250   evas_object_smart_callback_add(ewk_view_,
251                                  "policy,navigation,decide",
252                                  navigation_decide_callback,
253                                  this);
254
255   // policy,newwindow,decide
256   auto newwindow_decide_callback = [](void* user_data,
257                                       Evas_Object*,
258                                       void* event_info) {
259     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
260     Ewk_Policy_Decision* policy =
261             static_cast<Ewk_Policy_Decision*>(event_info);
262
263     const char* url = ewk_policy_decision_url_get(policy);
264
265     if (self->listener_) {
266       if (self->listener_->OnDidNavigation(self->view_, url) &&
267          self->listener_->OnDidOpenWindow(self->view_, url)) {
268          ewk_policy_decision_use(policy);
269       } else {
270         ewk_policy_decision_ignore(policy);
271       }
272     } else {
273       ewk_policy_decision_use(policy);
274     }
275   };
276   evas_object_smart_callback_add(ewk_view_,
277                                  "policy,newwindow,decide",
278                                  newwindow_decide_callback,
279                                  this);
280   smart_callbacks_["policy,navigation,decide"] = navigation_decide_callback;
281   smart_callbacks_["policy,newwindow,decide"] = newwindow_decide_callback;
282 }
283
284 void WebViewImpl::InitQuotaExceededCallback() {
285   // TODO(sngn.lee): Need callback interface - OnQutaExceed
286   // check http://tizen.org/privilege/unlimitedstorage
287
288   // callback for database quota exceeded
289   // TODO(wy80.choi): AARCH64:
290   //   Fix ewk api to use stdint types instead of longlong.
291   auto database_exceeded_callback = [](Evas_Object* view,
292                                        Ewk_Security_Origin* origin,
293                                        const char*,
294                                        unsigned long long,
295                                        void* user_data) -> Eina_Bool {
296     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
297     if (self == NULL || self->listener_ == NULL)
298       return EINA_TRUE;
299
300     auto result_handler = [view](bool result) {
301       LOGGER(DEBUG) << "database quota Permission Result : " << result;
302       ewk_view_exceeded_database_quota_reply(view, result);
303     };
304     std::stringstream url;
305     url << ewk_security_origin_protocol_get(origin)
306         << "://"
307         << ewk_security_origin_host_get(origin)
308         << ":"
309         << ewk_security_origin_port_get(origin);
310     self->listener_->OnQuotaExceed(
311         self->view_,
312         url.str(),
313         result_handler);
314     return EINA_TRUE;
315   };
316   ewk_view_exceeded_database_quota_callback_set(
317     ewk_view_,
318     database_exceeded_callback,
319     this);
320
321   // callback for indexed database quota exceeded
322   // TODO(wy80.choi): AARCH64:
323   //   Fix ewk api to use stdint types instead of longlong.
324   auto indexed_db_exceeded_callback = [](Evas_Object* view,
325                                        Ewk_Security_Origin* origin,
326                                        long long,
327                                        void* user_data) -> Eina_Bool {
328     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
329     if (self == NULL || self->listener_ == NULL)
330       return EINA_TRUE;
331
332     auto result_handler = [view](bool result) {
333       LOGGER(DEBUG) << "indexed db quota Permission Result : " << result;
334       ewk_view_exceeded_indexed_database_quota_reply(view, result);
335     };
336     std::stringstream url;
337     url << ewk_security_origin_protocol_get(origin)
338         << "://"
339         << ewk_security_origin_host_get(origin)
340         << ":"
341         << ewk_security_origin_port_get(origin);
342     self->listener_->OnQuotaExceed(
343         self->view_,
344         url.str(),
345         result_handler);
346     return EINA_TRUE;
347   };
348   ewk_view_exceeded_indexed_database_quota_callback_set(
349     ewk_view_,
350     indexed_db_exceeded_callback,
351     this);
352
353   // callback for localfile quota exceeded
354   // TODO(wy80.choi): AARCH64:
355   //   Fix ewk api to use stdint types instead of longlong.
356   auto localfile_exceeded_callback = [](Evas_Object* view,
357                                        Ewk_Security_Origin* origin,
358                                        long long,
359                                        void* user_data) -> Eina_Bool {
360     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
361     if (self == NULL || self->listener_ == NULL)
362       return EINA_TRUE;
363
364     auto result_handler = [view](bool result) {
365       LOGGER(DEBUG) << "local file quota Permission Result : " << result;
366       ewk_view_exceeded_local_file_system_quota_reply(view, result);
367     };
368     std::stringstream url;
369     url << ewk_security_origin_protocol_get(origin)
370         << "://"
371         << ewk_security_origin_host_get(origin)
372         << ":"
373         << ewk_security_origin_port_get(origin);
374     self->listener_->OnQuotaExceed(
375         self->view_,
376         url.str(),
377         result_handler);
378     return EINA_TRUE;
379   };
380   ewk_view_exceeded_local_file_system_quota_callback_set(
381     ewk_view_,
382     localfile_exceeded_callback,
383     this);
384 }
385
386 void WebViewImpl::InitIPCMessageCallback() {
387   // wrt,message
388   auto wrt_message_callback = [](void* user_data,
389                                  Evas_Object*,
390                                  void* event_info) {
391     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
392     Ewk_IPC_Wrt_Message_Data* msg =
393         static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
394     if (self->listener_)
395       self->listener_->OnReceivedWrtMessage(self->view_, msg);
396   };
397   evas_object_smart_callback_add(ewk_view_,
398                                  "wrt,message",
399                                  wrt_message_callback,
400                                  this);
401   smart_callbacks_["wrt,message"] = wrt_message_callback;
402 }
403
404 void WebViewImpl::InitOrientaionLockCallback() {
405   // Orientation lock callback
406   auto orientation_lock_callback = [](Evas_Object*,
407                                       Eina_Bool need_lock,
408                                       int orientation,
409                                       void* user_data) -> Eina_Bool {
410     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
411     if (self->listener_) {
412       self->listener_->OnOrientationLock(self->view_,
413                                          need_lock,
414                                          ToNativeRotation(orientation));
415     }
416     return EINA_TRUE;
417   };
418   ewk_view_orientation_lock_callback_set(ewk_view_,
419                                          orientation_lock_callback,
420                                          this);
421 }
422
423 void WebViewImpl::InitConsoleMessageCallback() {
424   // console log
425   auto console_message_callback = [](void* user_data,
426                                  Evas_Object*,
427                                  void* event_info) {
428     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
429     if (!self->listener_) {
430       return;
431     }
432     Ewk_Console_Message* msg = static_cast<Ewk_Console_Message*>(event_info);
433     unsigned int line_number = ewk_console_message_line_get(msg);
434
435     std::stringstream buf;
436     if (line_number) {
437         buf << ewk_console_message_source_get(msg) << ":";
438         buf << line_number << ":";
439     }
440     buf << ewk_console_message_text_get(msg);
441     int level = ewk_console_message_level_get(msg);
442     self->listener_->OnConsoleMessage(buf.str(), level);
443   };
444   evas_object_smart_callback_add(ewk_view_,
445                                  "console,message",
446                                  console_message_callback,
447                                  this);
448   smart_callbacks_["console,message"] = console_message_callback;
449 }
450
451 void WebViewImpl::InitCustomContextMenuCallback() {
452   auto custom_context_menu_callback = [](void* user_data,
453                                          Evas_Object*,
454                                          void* event_info) {
455     Ewk_Context_Menu* contextmenu = static_cast<Ewk_Context_Menu*>(event_info);
456     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
457     bool disabled = false;
458     if (self->listener_ &&
459         self->listener_->OnContextMenuDisabled(self->view_)) {
460       disabled = true;
461     }
462     int cnt = ewk_context_menu_item_count(contextmenu);
463     for (unsigned idx = cnt-1; idx > 0; --idx) {
464       auto* item = ewk_context_menu_nth_item_get(contextmenu, idx);
465       Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
466       switch (tag) {
467         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
468         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
469         case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
470         case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
471         case EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_IMAGE_TO_DISK:
472           ewk_context_menu_item_remove(contextmenu, item);
473           break;
474         default:
475           if (disabled)
476             ewk_context_menu_item_remove(contextmenu, item);
477       }
478     }
479   };
480   evas_object_smart_callback_add(ewk_view_,
481                                  "contextmenu,customize",
482                                  custom_context_menu_callback,
483                                  this);
484   smart_callbacks_["contextmenu,customize"] = custom_context_menu_callback;
485 }
486
487 void WebViewImpl::InitRotationCallback() {
488   // rotation support
489   ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
490   rotation_handler_id_ = window_->AddRotationHandler(
491                                   std::bind(&WebViewImpl::OnRotation,
492                                   this,
493                                   std::placeholders::_1));
494 }
495
496 void WebViewImpl::InitWindowCreateCallback() {
497   auto create_callback = [](void* user_data,
498                             Evas_Object*,
499                             void* event_info) {
500     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
501     if (!self->listener_) {
502       return;
503     }
504     WebView* new_view = new WebView(self->window_, self->context_);
505     self->listener_->OnCreatedNewWebView(self->view_, new_view);
506     *(static_cast<Evas_Object **>(event_info)) = new_view->evas_object();
507   };
508
509   auto close_callback = [](void* user_data,
510                             Evas_Object*,
511                             void*) {
512     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
513     if (!self->listener_) {
514       return;
515     }
516     self->listener_->OnClosedWebView(self->view_);
517   };
518   evas_object_smart_callback_add(ewk_view_,
519                                  "create,window",
520                                  create_callback,
521                                  this);
522   evas_object_smart_callback_add(ewk_view_,
523                                  "close,window",
524                                  close_callback,
525                                  this);
526
527   smart_callbacks_["create,window"] = create_callback;
528   smart_callbacks_["close,window"] = close_callback;
529 }
530
531 void WebViewImpl::InitFullscreenCallback() {
532   auto enter_callback = [](void* user_data,
533                             Evas_Object*,
534                             void* /*event_info*/) {
535     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
536     self->fullscreen_ = true;
537     self->window_->FullScreen(true);
538   };
539   auto exit_callback =  [](void* user_data,
540                             Evas_Object*,
541                             void* /*event_info*/) {
542     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
543     self->fullscreen_ = false;
544     self->window_->FullScreen(false);
545   };
546   evas_object_smart_callback_add(ewk_view_,
547                                  "fullscreen,enterfullscreen",
548                                  enter_callback,
549                                  this);
550   evas_object_smart_callback_add(ewk_view_,
551                                  "fullscreen,exitfullscreen",
552                                  exit_callback,
553                                  this);
554   smart_callbacks_["fullscreen,enterfullscreen"] = enter_callback;
555   smart_callbacks_["fullscreen,exitfullscreen"] = exit_callback;
556 }
557
558 void WebViewImpl::InitNotificationPermissionCallback() {
559   auto request_callback = [](Evas_Object*,
560                              Ewk_Notification_Permission_Request* request,
561                              void* user_data) {
562     LOGGER(DEBUG) << "Notification Permission Request";
563     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
564     if (!self->listener_) {
565       ewk_notification_permission_reply(request, EINA_FALSE);
566       return EINA_TRUE;
567     }
568
569     ewk_notification_permission_request_suspend(request);
570     auto result_handler = [request](bool result) {
571       LOGGER(DEBUG) << "Notification Permission Result : %d" << result;
572       ewk_notification_permission_reply(request, result);
573     };
574     const Ewk_Security_Origin* ewk_origin =
575         ewk_notification_permission_request_origin_get(request);
576
577     std::stringstream url;
578     url << ewk_security_origin_protocol_get(ewk_origin)
579         << "://"
580         << ewk_security_origin_host_get(ewk_origin)
581         << ":"
582         << ewk_security_origin_port_get(ewk_origin);
583     self->listener_->OnNotificationPermissionRequest(
584         self->view_,
585         url.str(),
586         result_handler);
587     return EINA_TRUE;
588   };
589   ewk_view_notification_permission_callback_set(ewk_view_,
590                                                 request_callback,
591                                                 this);
592 }
593
594 void WebViewImpl::InitGeolocationPermissionCallback() {
595   auto permission_callback = [](
596       Evas_Object*,
597       Ewk_Geolocation_Permission_Request* request,
598       void* user_data) {
599     LOGGER(DEBUG) << "Geolocation Permission Request";
600     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
601     if (self == NULL || self->listener_ == NULL) {
602       ewk_geolocation_permission_reply(request, EINA_FALSE);
603       return EINA_TRUE;
604     }
605     ewk_geolocation_permission_request_suspend(request);
606
607     const Ewk_Security_Origin* ewk_origin =
608         ewk_geolocation_permission_request_origin_get(request);
609     auto result_handler = [request](bool result) {
610       LOGGER(DEBUG) << "Geolocation Permission Result : " << result;
611       ewk_geolocation_permission_reply(request, result);
612     };
613
614     std::stringstream url;
615     url << ewk_security_origin_protocol_get(ewk_origin)
616         << "://"
617         << ewk_security_origin_host_get(ewk_origin)
618         << ":"
619         << ewk_security_origin_port_get(ewk_origin);
620
621     self->listener_->OnGeolocationPermissionRequest(
622         self->view_,
623         url.str(),
624         result_handler);
625     return EINA_TRUE;
626   };
627   ewk_view_geolocation_permission_callback_set(ewk_view_,
628                                                permission_callback,
629                                                this);
630 }
631
632 void WebViewImpl::InitAuthenticationCallback() {
633   auto auth_callback = [](void* user_data,
634                           Evas_Object*,
635                           void* event_info) {
636     LOGGER(DEBUG) << "Authentication Request";
637     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
638     Ewk_Auth_Challenge* auth_challenge =
639         static_cast<Ewk_Auth_Challenge*>(event_info);
640
641     if (self == NULL || self->listener_ == NULL) {
642       ewk_auth_challenge_credential_cancel(auth_challenge);
643       return;
644     }
645     auto result_handler = [auth_challenge](bool submit,
646                                     const std::string& id,
647                                     const std::string& password) {
648       LOGGER(DEBUG) << "Authentication Result : submit = " << submit;
649       if (!submit) {
650         ewk_auth_challenge_credential_cancel(auth_challenge);
651         return;
652       }
653       ewk_auth_challenge_credential_use(auth_challenge,
654                                         id.c_str(),
655                                         password.c_str());
656     };
657     ewk_auth_challenge_suspend(auth_challenge);
658     const char* message =
659         ewk_auth_challenge_realm_get(auth_challenge);
660     std::string url = self->GetUrl();
661     self->listener_->OnAuthenticationRequest(self->view_,
662                                              url,
663                                              message,
664                                              result_handler);
665   };
666   // "authentication,challenge"
667   evas_object_smart_callback_add(ewk_view_,
668                                  "authentication,challenge",
669                                  auth_callback,
670                                  this);
671   smart_callbacks_["authentication,challenge"] = auth_callback;
672 }
673
674 void WebViewImpl::InitCertificateAllowCallback() {
675   auto certi_callback = [](void* user_data,
676                            Evas_Object*,
677                            void* event_info) {
678     WebViewImpl* self = static_cast<WebViewImpl*>(user_data);
679     Ewk_Certificate_Policy_Decision* policy =
680       static_cast<Ewk_Certificate_Policy_Decision*>(event_info);
681
682     if (self == NULL || self->listener_ == NULL) {
683       ewk_certificate_policy_decision_allowed_set(policy, EINA_FALSE);
684       return;
685     }
686
687     ewk_certificate_policy_decision_suspend(policy);
688     auto result_handler = [policy](bool allow) {
689       ewk_certificate_policy_decision_allowed_set(policy, allow);
690     };
691
692     auto ptr = ewk_certificate_policy_decision_url_get(policy);
693     std::string url(ptr ? ptr : "");
694     ptr = ewk_certificate_policy_decision_certificate_pem_get(policy);
695     std::string pem(ptr ? ptr : "");
696     self->listener_->OnCertificateAllowRequest(self->view_,
697                                                url,
698                                                pem,
699                                                result_handler);
700   };
701   evas_object_smart_callback_add(ewk_view_,
702                                  "request,certificate,confirm",
703                                  certi_callback,
704                                  this);
705   smart_callbacks_["request,certificate,confirm"] = certi_callback;
706 }
707
708
709 std::string WebViewImpl::GetUrl() {
710   return std::string(ewk_view_url_get(ewk_view_));
711 }
712
713 Evas_Object* WebViewImpl::evas_object() const {
714   return ewk_view_;
715 }
716
717 void WebViewImpl::OnRotation(int degree) {
718   ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
719 }
720
721 void WebViewImpl::OnKeyEvent(Ea_Callback_Type key_type) {
722   std::string keyname;
723   if (key_type == EA_CALLBACK_BACK) {
724     if (fullscreen_) {
725       ewk_view_fullscreen_exit(ewk_view_);
726       return;
727     }
728     if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
729       return;
730     }
731     keyname = kKeyNameBack;
732   } else if (key_type == EA_CALLBACK_MORE) {
733     keyname = kKeyNameMenu;
734   } else {
735     return;
736   }
737
738   if (listener_)
739     listener_->OnHardwareKey(view_, keyname);
740 }
741
742 void WebViewImpl::SetEventListener(WebView::EventListener* listener) {
743   listener_ = listener;
744 }
745
746 void WebViewImpl::SetAppInfo(const std::string& app_name,
747                              const std::string& version) {
748   std::string ua = app_name + "/" + version;
749   ewk_view_application_name_for_user_agent_set(ewk_view_, ua.c_str());
750 }
751 bool WebViewImpl::SetUserAgent(const std::string& user_agent) {
752   return ewk_view_user_agent_set(ewk_view_, user_agent.c_str());
753 }
754
755 }  // namespace wrt