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