2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file view_logic.cpp
18 * @author Pawel Sikorski (p.sikorsk@samsung.com)
19 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
20 * @author Yunchan Cho (yunchan.cho@samsung.com)
21 * @brief View logic for Webkit2
23 #include "view_logic.h"
27 #include <dpl/assert.h>
28 #include <dpl/log/log.h>
29 #include <dpl/optional.h>
30 #include <dpl/string.h>
32 #include <appcore-common.h>
35 #include <widget_model.h>
36 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
37 #include <dpl/utils/wrt_global_settings.h>
39 #include <common/application_data.h>
40 #include <common/application_launcher.h>
41 #include <common/scheme.h>
43 #include <common/view_logic_apps_support.h>
44 #include <common/view_logic_custom_header_support.h>
45 #include <common/view_logic_password_support.h>
46 #include <common/view_logic_security_support.h>
47 #include <common/view_logic_security_origin_support.h>
48 #include <common/view_logic_storage_support.h>
49 #include <common/view_logic_uri_support.h>
50 #include <common/view_logic_user_agent_support.h>
51 #include <common/view_logic_vibration_support.h>
52 #include <common/view_logic_web_notification_support.h>
53 #include <view_logic_scheme_support.h>
54 #include <view_logic_filesystem_support.h>
55 #include <view_logic_geolocation_support_webkit2.h>
56 #include <view_logic_usermedia_support.h>
57 #include <view_logic_web_storage_support.h>
58 #include "bundles/plugin_module_support.h"
59 #include <popup-runner/PopupInvoker.h>
62 #include <js_overlay_types.h>
63 #include <i_runnable_widget_object.h>
64 #include <profiling_util.h>
65 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
66 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
67 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
68 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
70 #include <appsvc/appsvc.h>
73 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
74 const char * const uriBlockedMessageName = "uri_block_msg";
75 const char * const uriChangedMessageName = "uri_changed_msg";
76 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
77 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
78 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
79 const char * const URICHANGE_BLOCKED_URL = "null";
80 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
81 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
83 const char * const IME_STATE_ON = "on";
84 const char * const IME_STATE_OFF = "off";
87 const char * const EWK_LOAD_STARTED = "load,started";
88 const char * const EWK_LOAD_FINISHED = "load,finished";
89 const char * const EWK_TITLE_CHANGED = "title,changed";
90 const char * const EWK_LOAD_PROGRESS = "load,progress";
91 const char * const EWK_LOAD_PROGRESS_FINISHED = "load,progress,finished";
92 const char * const EWK_PROCESS_CRASHED = "process,crashed";
94 const char * const EWK_CREATE_WINDOW = "create,window";
95 const char * const EWK_CLOSE_WINDOW = "close,window";
97 const char * const EWK_POLICY_NAVIGATION_DECIDE = "policy,navigation,decide";
98 const char * const EWK_POLICY_NEWWINDOW_DECIDE = "policy,newwindow,decide";
99 const char * const EWK_POLICY_RESPONSE_DECIDE = "policy,response,decide";
100 // WKPageContextMenuClient
101 const char * const EWK_CONTEXTMENU_CUSTOMIZE = "contextmenu,customize";
103 const char * const EWK_FORM_SUBMIT = "form,submit";
104 // EWK Geolocation Callback
105 const char * const EWK_REQUEST_GEOLOCATION_PERMISSION =
106 "request,geolocation,permission";
107 // EWK Notification Callback
108 const char * const EWK_NOTIFICATION_SHOW = "notification,show";
109 const char * const EWK_NOTIFICATION_CANCEL = "notification,cancel";
110 const char * const EWK_NOTIFICATION_PERMISSION_REQUEST =
111 "notification,permission,request";
112 // EWK Vibration Callback
113 const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
114 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
116 const char * const EWK_CONTEXT_EXCEEDED_QUOATA = "database,quota,exceeded";
117 const char * const EWK_FILESYSTEM_PERMISSION_REQUEST = "filesystem,permission,request";
118 const char * const EWK_FULLSCREEN_ENTER = "fullscreen,enterfullscreen";
119 const char * const EWK_FULLSCREEN_EXIT = "fullscreen,exitfullscreen";
122 const char * const EWK_INPUTMETHOD_CHANGED = "inputmethod,changed";
123 const char * const EWK_EDITORCLIENT_IME_OPENED = "editorclient,ime,opened";
124 const char * const EWK_EDITORCLIENT_IME_CLOSED = "editorclient,ime,closed";
126 // EWK Usermedia Callback
127 const char * const EWK_USERMEDIA_PERMISSION_REQUEST = "usermedia,permission,request";
130 const char * const EWK_PROTOCOLHANDLER_REGISTRATION = "protocolhandler,registration,requested";
131 const char * const EWK_PROTOCOLHANDLER_ISREGISTERED = "protocolhandler,isregistered";
132 const char * const EWK_PROTOCOLHANDLER_UNREGISTRATION = "protocolhandler,unregistration,requested";
133 const char * const EWK_CONTENTHANDLER_REGISTRATION = "contenthandler,registration,requested";
134 const char * const EWK_CONTENTHANDLER_ISREGISTERED = "contenthandler,isregistered";
135 const char * const EWK_CONTENTHANDLER_UNREGISTRATION = "contenthandler,unregistration,requested";
137 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
138 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
139 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
140 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
141 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
142 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
145 ViewLogic::ViewLogic():
150 m_cbs(new WRT::UserDelegates),
151 m_isBackgroundReload(false),
152 m_appsSupport(new ViewModule::AppsSupport()),
153 m_vibrationSupport(),
154 m_attachedToCustomHandlerDao(false)
158 ViewLogic::~ViewLogic ()
160 detachFromCustomHandlersDao();
163 void ViewLogic::createWebView(Ewk_Context* context,
167 initializeEwkContext(context);
168 Assert(NULL != m_ewkContext);
171 createEwkView(evas_object_evas_get(m_window));
174 void ViewLogic::destroyWebView()
177 finalizeEwkContext();
181 void ViewLogic::initialize()
183 LogDebug("Initializing");
184 ApplicationLauncherSingleton::Instance().Touch();
185 appcore_set_event_callback(
186 APPCORE_EVENT_LOW_MEMORY,
187 &appcoreLowMemoryCallback,
191 void ViewLogic::terminate()
193 LogDebug("terminating view logic");
197 LogError("Widget model not created");
202 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
204 LogDebug("View prepare");
208 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
209 Assert(NULL != m_ewkContext);
212 ADD_PROFILING_POINT("initializeSupport", "start");
214 ADD_PROFILING_POINT("initializeSupport", "stop");
216 ewkClientInit(m_currentEwkView);
217 ADD_PROFILING_POINT("prepareEwkView", "start");
218 prepareEwkView(m_currentEwkView);
219 ADD_PROFILING_POINT("prepareEwkView", "stop");
220 initializePluginLoading();
223 void ViewLogic::showWidget()
225 LogDebug("showing widget");
226 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
227 if (m_currentUri.empty()) {
228 LogError("Localized current URI doesn't exist");
232 LogInfo("m_currentUri: " << m_currentUri);
235 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
237 if (!m_cbs->bufferSet.empty()) {
238 m_cbs->bufferSet(m_currentEwkView);
242 void ViewLogic::hideWidget()
244 LogDebug("hiding widget");
245 ViewModule::StorageSupport::deinitializeStorage(m_model);
246 m_appsSupport->deinitialize();
249 // m_vibrationSupport->deinitialize();
251 while (m_ewkViewList.size()) {
252 LogInfo("pop webview: " << m_ewkViewList.back());
253 removeEwkView(m_ewkViewList.back());
255 m_ewkViewList.clear();
258 void ViewLogic::suspendWidget()
260 LogInfo("Pausing widget");
263 LogDebug("Request bundle to suspend");
264 PluginModuleSupport::suspend(m_ewkContext);
266 if (!m_currentEwkView) {
267 LogWarning("Cannot suspend widget without view");
269 suspendWebkit(m_currentEwkView);
272 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
274 // call user callback
275 if (!m_cbs->suspend.empty()) {
276 m_cbs->suspend(true);
280 void ViewLogic::resumeWidget()
282 LogInfo("Resume widget");
285 LogDebug("Request bundle to resume");
286 PluginModuleSupport::resume(m_ewkContext);
288 if (m_currentEwkView) {
289 resumeWebkit(m_currentEwkView);
292 /* window system team recomend removing this win_raise code. */
295 elm_win_raise(m_window);
298 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
300 // call user callback
301 if (!m_cbs->resume.empty()) {
306 void ViewLogic::resetWidget()
308 LogInfo("Resetting Widget");
310 // check if already created webview exists
311 if (!m_ewkViewList.size()) {
312 // create new webview
313 createEwkView(evas_object_evas_get(m_window));
315 ewkClientInit(m_currentEwkView);
316 prepareEwkView(m_currentEwkView);
318 // check if current url is service url for this tizen service
319 std::string requestedUri =
320 ViewModule::UriSupport::getUri(m_model, m_startUrl);
321 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
322 DPL::FromUTF8String(requestedUri.c_str()),
325 const char* currentUri = ewk_view_url_get(m_currentEwkView);
326 if (!currentUri && 0 == strlen(currentUri)) {
327 LogError("Fail to get uri from ewk_view_url_get");
332 PluginModuleSupport::resume(m_ewkContext);
333 resumeWebkit(m_currentEwkView);
334 if (DPL::ToUTF8String(*servicedUri) == currentUri) {
335 LogInfo("current page is raised");
336 // set only encoded bundle
337 double scale = elm_config_scale_get();
338 PluginModuleSupport::setCustomProperties(
341 ApplicationDataSingleton::Instance().getEncodedBundle());
342 PluginModuleSupport::dispatchJavaScriptEvent(
344 WrtPlugins::W3C::ServiceCustomEvent,
347 LogInfo("service page is loaded");
348 m_currentUri = DPL::ToUTF8String(*servicedUri);
349 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
351 elm_win_raise(m_window);
352 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
355 // call user callback
356 if (!m_cbs->reset.empty()) {
359 if (!m_cbs->bufferSet.empty()) {
360 m_cbs->bufferSet(m_currentEwkView);
364 void ViewLogic::backward()
366 if (ewk_view_back_possible(m_currentEwkView)) {
367 ewk_view_back(m_currentEwkView);
369 if (1 >= m_ewkViewList.size()) {
370 // If there is no previous page, widget move to backgroud.
371 LogInfo("Widget move to backgroud");
372 elm_win_lower(m_window);
374 // Back to previous webview
375 LogInfo("Widget move to previous webview");
376 ecore_idler_add(windowCloseIdlerCallback, this);
381 void ViewLogic::reload()
383 ewk_view_reload(m_currentEwkView);
386 void ViewLogic::forward()
388 if (ewk_view_forward_possible(m_currentEwkView)) {
389 ewk_view_forward(m_currentEwkView);
393 void ViewLogic::reloadStartPage()
395 LogInfo("Reload Start Page");
396 // prevent fail to load plugin bundle side
397 m_isBackgroundReload = true;
398 PluginModuleSupport::resume(m_ewkContext);
400 if (m_ewkViewList.size() != 0) {
401 while (m_ewkViewList.size() > 0) {
402 if (!m_cbs->bufferUnset.empty()) {
403 m_cbs->bufferUnset(m_currentEwkView);
405 removeEwkView(m_currentEwkView);
409 // create new webview
410 createEwkView(evas_object_evas_get(m_window));
411 ewkClientInit(m_currentEwkView);
414 prepareEwkView(m_currentEwkView);
415 initializePluginLoading();
418 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
421 if (!m_cbs->bufferSet.empty()) {
422 m_cbs->bufferSet(m_currentEwkView);
424 LogInfo("Reloading Start Page is done!");
427 Evas_Object* ViewLogic::getCurrentWebview()
429 LogInfo("get current webview");
430 return m_currentEwkView;
433 void ViewLogic::fireJavascriptEvent(int event, void* data)
435 PluginModuleSupport::dispatchJavaScriptEvent(
437 static_cast<WrtPlugins::W3C::CustomEventType>(event),
441 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
446 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
448 LogInfo("initializeEwkContext called");
449 Assert(newEwkContext && "Ewk_Context provided can not be null");
450 // bundle callback setting
451 ewk_context_message_from_injected_bundle_callback_set(
453 contextMessageFromInjectedBundleCallback,
454 static_cast<void*>(this));
456 // proxy server setting
457 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
458 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
459 || (strstr(proxyAddress, "0.0.0.0")))
461 LogInfo("proxy address is empty");
462 ewk_context_proxy_uri_set(newEwkContext, NULL);
464 LogInfo("proxy address [" << proxyAddress << "]");
465 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
474 const char *theme = elm_theme_get(NULL);
477 LogInfo("theme is " << m_theme);
480 // Ewk download callback (WKContextDownloadClient)
481 ewk_context_did_start_download_callback_set(
483 didStartDownloadCallback,
486 // set to member value
487 m_ewkContext = newEwkContext;
490 void ViewLogic::finalizeEwkContext()
492 LogInfo("finalizeEwkContext called");
493 ewk_context_message_from_injected_bundle_callback_set(
497 // ewk_context_delete(m_ewkContext);
501 void ViewLogic::initializeSupport()
503 // set local stroage database path
504 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
505 ewk_context_web_storage_path_set(m_ewkContext,
506 dao.getPrivateLocalStoragePath().c_str());
507 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
508 ViewModule::StorageSupport::initializeStorage(m_model);
509 m_appsSupport->initialize(m_model);
510 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
513 // m_vibrationSupport->initialize();
516 void ViewLogic::initializePluginLoading()
518 // inform wrt information for plugin loading to web process
519 PluginModuleSupport::start(
522 elm_config_scale_get(),
523 ApplicationDataSingleton::Instance().getEncodedBundle(),
525 m_model->SettingList.Get().isEncrypted());
528 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
529 Assert(NULL != wkView && "ewk_view not created at this point");
530 // WKPageLoaderClient
531 evas_object_smart_callback_add(
536 evas_object_smart_callback_add(
539 loadFinishedCallback,
541 evas_object_smart_callback_add(
544 titleChangedCallback,
546 evas_object_smart_callback_add(
549 loadProgressCallback,
551 evas_object_smart_callback_add(
553 EWK_LOAD_PROGRESS_FINISHED,
554 loadProgressFinishedCallback,
556 evas_object_smart_callback_add(
559 processCrashedCallback,
563 evas_object_smart_callback_add(
566 createWindowCallback,
568 evas_object_smart_callback_add(
574 // WKPagePolicyClient
575 evas_object_smart_callback_add(
577 EWK_POLICY_NAVIGATION_DECIDE,
578 policyNavigationDecideCallback,
580 evas_object_smart_callback_add(
582 EWK_POLICY_NEWWINDOW_DECIDE,
583 policyNewWindowDecideCallback,
585 evas_object_smart_callback_add(
587 EWK_POLICY_RESPONSE_DECIDE,
588 pageResponseDecideCallback,
591 // WKPageContextMenuClient
592 evas_object_smart_callback_add(
594 EWK_CONTEXTMENU_CUSTOMIZE,
595 contextmenuCustomizeCallback,
599 evas_object_smart_callback_add(
605 // EWK Geolocation Callback
606 evas_object_smart_callback_add(
608 EWK_REQUEST_GEOLOCATION_PERMISSION,
609 geolocationPermissionRequestCallback,
612 // EWK Notification Callback
613 evas_object_smart_callback_add(
615 EWK_NOTIFICATION_SHOW,
616 notificationShowCallback,
618 evas_object_smart_callback_add(
620 EWK_NOTIFICATION_CANCEL,
621 notificationCancelCallback,
623 evas_object_smart_callback_add(
625 EWK_NOTIFICATION_PERMISSION_REQUEST,
626 notificationPermissionRequestCallback,
629 // EWK Vibration Callback
630 evas_object_smart_callback_add(
632 EWK_VIBRATION_VIBRATE,
633 vibrationVibrateCallback,
635 evas_object_smart_callback_add(
637 EWK_VIBRATION_CANCEL,
638 vibrationCancelCallback,
640 evas_object_smart_callback_add(
642 EWK_CONTEXT_EXCEEDED_QUOATA,
643 databaseUsagePermissionRequestCallback,
645 evas_object_smart_callback_add(
647 EWK_FILESYSTEM_PERMISSION_REQUEST,
648 fileSystemPermissionRequestCallback,
651 // EWK Orientation Callback
652 //ewk_view_orientation_lock_callback_set(
654 // orientationLockCallback,
657 // Fullscreen API callbacks
658 evas_object_smart_callback_add(
660 EWK_FULLSCREEN_ENTER,
661 enterFullscreenCallback,
663 evas_object_smart_callback_add(
666 exitFullscreenCallback,
670 // when ime start to be showed on the webview,
671 // this callback will be called
672 evas_object_smart_callback_add(
674 EWK_INPUTMETHOD_CHANGED,
678 // this callback will be called
679 // when ime finishes to be showed on the webview
680 // "event_info" arg of this callback is always NULL point
681 // if web content should know size of ime,
682 // use "inputmethod,changed" instead of this.
684 evas_object_smart_callback_add(
686 EWK_EDITORCLIENT_IME_OPENED,
690 // when ime finished to be hidden,
691 // this callback will be called
692 evas_object_smart_callback_add(
694 EWK_EDITORCLIENT_IME_CLOSED,
698 // usermedia callback
699 evas_object_smart_callback_add(
701 EWK_USERMEDIA_PERMISSION_REQUEST,
702 usermediaPermissionRequestCallback,
705 // custom content/scheme handlers
706 evas_object_smart_callback_add(
708 EWK_PROTOCOLHANDLER_REGISTRATION,
709 protocolHandlerRegistrationCallback,
711 evas_object_smart_callback_add(
713 EWK_PROTOCOLHANDLER_ISREGISTERED,
714 protocolHandlerIsRegisteredCallback,
716 evas_object_smart_callback_add(
718 EWK_PROTOCOLHANDLER_UNREGISTRATION,
719 protocolHandlerUnregistrationCallback,
722 evas_object_smart_callback_add(
724 EWK_CONTENTHANDLER_REGISTRATION,
725 contentHandlerRegistrationCallback,
727 evas_object_smart_callback_add(
729 EWK_CONTENTHANDLER_ISREGISTERED,
730 contentHandlerIsRegisteredCallback,
732 evas_object_smart_callback_add(
734 EWK_CONTENTHANDLER_UNREGISTRATION,
735 contentHandlerUnregistrationCallback,
739 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
740 LogDebug("ewkClientDeinit");
741 Assert(NULL != wkView && "ewk_view not created at this point");
743 // WKPageLoaderClient
744 evas_object_smart_callback_del(
747 loadStartedCallback);
748 evas_object_smart_callback_del(
751 loadFinishedCallback);
752 evas_object_smart_callback_del(
755 titleChangedCallback);
756 evas_object_smart_callback_del(
759 loadProgressCallback);
760 evas_object_smart_callback_del(
762 EWK_LOAD_PROGRESS_FINISHED,
763 loadProgressFinishedCallback);
764 evas_object_smart_callback_del(
767 loadProgressCallback);
770 evas_object_smart_callback_del(
773 createWindowCallback);
774 evas_object_smart_callback_del(
777 closeWindowCallback);
779 // WKPagePolicyClient
780 evas_object_smart_callback_del(
782 EWK_POLICY_NAVIGATION_DECIDE,
783 policyNavigationDecideCallback);
784 evas_object_smart_callback_del(
786 EWK_POLICY_NEWWINDOW_DECIDE,
787 policyNewWindowDecideCallback);
788 evas_object_smart_callback_del(
790 EWK_POLICY_RESPONSE_DECIDE,
791 pageResponseDecideCallback);
793 // WKPageContextMenuClient
794 evas_object_smart_callback_del(
796 EWK_CONTEXTMENU_CUSTOMIZE,
797 contextmenuCustomizeCallback);
800 evas_object_smart_callback_del(
805 // EWK Geolocation Callback
806 evas_object_smart_callback_del(
808 EWK_REQUEST_GEOLOCATION_PERMISSION,
809 geolocationPermissionRequestCallback);
811 // EWK Notification Callback
812 evas_object_smart_callback_del(
814 EWK_NOTIFICATION_SHOW,
815 notificationShowCallback);
816 evas_object_smart_callback_del(
818 EWK_NOTIFICATION_CANCEL,
819 notificationCancelCallback);
820 evas_object_smart_callback_del(
822 EWK_NOTIFICATION_PERMISSION_REQUEST,
823 notificationPermissionRequestCallback);
825 // EWK Vibration Callback
826 evas_object_smart_callback_del(
828 EWK_VIBRATION_VIBRATE,
829 vibrationVibrateCallback);
830 evas_object_smart_callback_del(
832 EWK_VIBRATION_CANCEL,
833 vibrationCancelCallback);
835 evas_object_smart_callback_del(
837 EWK_CONTEXT_EXCEEDED_QUOATA,
838 databaseUsagePermissionRequestCallback);
839 evas_object_smart_callback_del(
841 EWK_FILESYSTEM_PERMISSION_REQUEST,
842 fileSystemPermissionRequestCallback);
844 // EWK Orientation Callback
845 //ewk_view_orientation_lock_callback_set(
850 // ime change/show/hide callback
851 evas_object_smart_callback_del(
853 EWK_INPUTMETHOD_CHANGED,
855 evas_object_smart_callback_del(
857 EWK_EDITORCLIENT_IME_OPENED,
859 evas_object_smart_callback_del(
861 EWK_EDITORCLIENT_IME_CLOSED,
864 // usermedia callback
865 evas_object_smart_callback_del(
867 EWK_USERMEDIA_PERMISSION_REQUEST,
868 usermediaPermissionRequestCallback);
870 // custom content/scheme handlers
871 evas_object_smart_callback_del(
873 EWK_PROTOCOLHANDLER_REGISTRATION,
874 protocolHandlerRegistrationCallback);
875 evas_object_smart_callback_del(
877 EWK_PROTOCOLHANDLER_ISREGISTERED,
878 protocolHandlerIsRegisteredCallback);
879 evas_object_smart_callback_del(
881 EWK_PROTOCOLHANDLER_UNREGISTRATION,
882 protocolHandlerUnregistrationCallback);
884 evas_object_smart_callback_del(
886 EWK_CONTENTHANDLER_REGISTRATION,
887 contentHandlerRegistrationCallback);
888 evas_object_smart_callback_del(
890 EWK_CONTENTHANDLER_ISREGISTERED,
891 contentHandlerIsRegisteredCallback);
892 evas_object_smart_callback_del(
894 EWK_CONTENTHANDLER_UNREGISTRATION,
895 contentHandlerUnregistrationCallback);
898 void ViewLogic::createEwkView(Evas* canvas)
900 LogDebug("createEwkVeiw");
902 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
903 Evas_Object* newEwkView = ewk_view_add_with_context(
906 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
909 LogError("WKView creation failed");
914 // even arguments pass the ewkContext, this API should be called
915 // after webkit Evas_Object is created
916 Ewk_Cookie_Manager *ewkCookieManager;
918 ewk_context_cookie_manager_get(m_ewkContext);
919 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
920 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
922 LogInfo("push webview: " << newEwkView);
923 m_ewkViewList.push_back(newEwkView);
924 m_currentEwkView = newEwkView;
927 void ViewLogic::setStartPage()
929 /* Start URI (as other uris) is now localized
930 * on WebProcess side */
931 m_currentUri = m_startUrl;
934 void ViewLogic::prepareEwkView(Evas_Object *wkView)
936 LogDebug("prepareEwkView called");
938 Ewk_Settings* settings = ewk_view_settings_get(wkView);
941 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
942 if (customUserAgent.empty()) {
943 auto userAgentString =
944 ViewModule::UserAgentSupport::getUserAgentFromVconf();
945 if (!userAgentString.empty()) {
946 LogDebug("Setting user agent as: " << userAgentString);
947 ewk_view_user_agent_set(wkView, userAgentString.c_str());
950 LogDebug("Setting custom user agent as: " << customUserAgent);
951 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
954 // set custom header : language
955 using namespace ViewModule::CustomHeaderSupport;
956 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
957 if (!customHeaderString.empty()) {
958 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
959 LogDebug("custom value=[" << customHeaderString << "]");
960 ewk_view_custom_header_add(wkView,
961 ACCEPT_LANGUAGE.c_str(),
962 customHeaderString.c_str());
965 // webkit NPAPI plugins is always on in wrt
966 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
968 // The followings are not implemeted yet by webkit2
969 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
970 // ewk_view_mode_set();
971 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
972 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
973 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
974 // elm_webview_show_magnifier_set(EINA_FALSE);
975 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
976 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
977 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
979 // disable zoom option when user click the input field
980 // this option is useful with the normal website
981 // for the make user friendly, disable auto zoom in the webapp
982 // The followings are not implemeted yet by webkit2
983 // elm_webview_input_field_zoom_set(EINA_FALSE);
985 // set cookie database path
986 // The followings are not implemeted yet by webkit2
987 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
989 // set visibility to WebCore. This value will be used for html5.
990 // also, this value will be changed in the suspend, resume
991 // or create window, close window.
992 ewk_view_page_visibility_state_set(wkView,
993 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
997 void ViewLogic::removeEwkView(Evas_Object *wkView)
999 LogInfo("removeEwkView called");
1001 Assert(0 != m_ewkViewList.size());
1003 // unregister webview callbacks
1004 ewkClientDeinit(wkView);
1006 // suspend NPAPI plugin - Not implemented by Webkit2
1007 // ewk_view_pause_or_resume_plugins();
1008 evas_object_del(wkView);
1009 m_ewkViewList.remove(wkView);
1012 void ViewLogic::resumeEwkView(Evas_Object *wkView)
1014 LogInfo("resumeEwkView called");
1017 // register webview callback
1018 ewkClientInit(wkView);
1021 resumeWebkit(wkView);
1026 void ViewLogic::suspendEwkView(Evas_Object *wkView)
1028 LogInfo("suspendEwkView called");
1032 suspendWebkit(wkView);
1034 // unregister webview callbacks
1035 ewkClientDeinit(wkView);
1040 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1042 LogDebug("resumeWebkit");
1045 // resume NPAPI plugin
1046 // The followings are not implemeted yet by webkit2
1047 // ewk_view_pause_or_resume_plugins(false);
1048 // ewk_view_pause_or_resume_video_audio(false);
1049 // ewk_view_javascript_resume();
1050 // ewk_view_enable_render();
1051 // ewk_view_reduce_plugins_frame_rate(false);
1052 ewk_view_resume(wkView);
1053 ewk_view_visibility_set(wkView, EINA_TRUE);
1054 ewk_view_page_visibility_state_set(wkView,
1055 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
1060 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1062 LogDebug("suspendWebkit");
1065 // suspend the followings
1066 // The followings are not implemeted yet by webkit2
1067 // ewk_view_pause_or_resume_plugins(true);
1068 // ewk_view_pause_or_resume_video_audio(true);
1070 // send visibility event to webpage
1071 ewk_view_page_visibility_state_set(wkView,
1072 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1074 ewk_view_suspend(wkView);
1075 ewk_view_visibility_set(wkView, EINA_FALSE);
1079 void ViewLogic::contextMessageFromInjectedBundleCallback(
1085 LogDebug("contextMessageFromInjectedBundleCallback called");
1087 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1088 // didRecieveMessageFromInjectedBundleCallback - returnData is null
1089 // didReceiveSynchronousMessageCallback - returnData isn't null
1090 // WKContextInjectedBundleClient bundleClient = {
1091 // kWKContextInjectedBundleClientCurrentVersion,
1092 // static_cast<void*>(this),
1093 // &didRecieveMessageFromInjectedBundleCallback,
1094 // &didReceiveSynchronousMessageCallback
1096 if (NULL == returnData) {
1097 This->didRecieveMessageFromInjectedBundle(name, body);
1099 This->didReceiveSynchronousMessage(name, body, returnData);
1103 void ViewLogic::didStartDownloadCallback(
1104 const char* downloadUrl,
1107 LogDebug("didStartDownloadCallback called");
1109 ViewLogic* This = static_cast<ViewLogic*>(data);
1110 Assert(downloadUrl);
1111 LogDebug("download url = " << downloadUrl);
1112 This->m_appsSupport->downloadRequest(
1118 void ViewLogic::loadStartedCallback(
1121 void* /*eventInfo*/)
1123 LogDebug("loadStartedCallback called");
1125 ViewLogic* This = static_cast<ViewLogic*>(data);
1126 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1128 // call loadFinish callback to wrt-client
1129 if (!This->m_cbs->loadStart.empty()) {
1130 This->m_cbs->loadStart(obj);
1135 void ViewLogic::loadFinishedCallback(
1138 void* /*eventInfo*/)
1140 LogDebug("loadFinishedCallback called");
1142 ViewLogic* This = static_cast<ViewLogic*>(data);
1145 const char* url = ewk_view_url_get(This->m_currentEwkView);
1146 if (NULL == url || strlen(url) == 0) {
1147 LogError("url is empty");
1149 DPL::OptionalString jsOptionalString =
1150 ViewModule::PasswordSupport::jsForAutoFillData(url);
1151 if (jsOptionalString.IsNull()) {
1152 LogError("Fail to get JS String");
1154 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1156 if(EINA_FALSE == ewk_view_script_execute(
1157 This->m_currentEwkView,
1159 didRunJavaScriptCallback,
1162 LogError("JS for auto fill data failed.");
1167 // call loadFinish callback to wrt-client
1168 if (!This->m_cbs->loadFinish.empty()) {
1169 This->m_cbs->loadFinish(obj);
1172 // set only encoded bundle
1173 double scale = elm_config_scale_get();
1174 PluginModuleSupport::setCustomProperties(
1177 ApplicationDataSingleton::Instance().getEncodedBundle());
1178 // check if 'appsevice' event is registed at the current frames.
1179 // If so, dispatch the event to frames.
1180 PluginModuleSupport::dispatchJavaScriptEvent(
1182 WrtPlugins::W3C::ServiceCustomEvent,
1185 // In this case, widget is reloaded in the background.
1186 // After finished load, bundle should disconnent callback.
1187 if (This->m_isBackgroundReload) {
1188 PluginModuleSupport::suspend(This->m_ewkContext);
1189 ewk_view_suspend(This->m_currentEwkView);
1190 This->m_isBackgroundReload = false;
1194 void ViewLogic::titleChangedCallback(
1196 Evas_Object* /*obj*/,
1199 LogDebug("titleChangedCallback called");
1201 ViewLogic* This = static_cast<ViewLogic*>(data);
1203 const char* title = static_cast<char*>(eventInfo);
1205 if (0 == strlen(title)) {
1206 LogDebug("title data is empty");
1209 LogDebug("Title = [" << title << "]");
1210 This->m_schemeSupport->HandleTizenScheme(title,
1212 This->m_currentEwkView);
1215 void ViewLogic::loadProgressCallback(
1217 Evas_Object* /*obj*/,
1220 double* progress = static_cast<double*>(eventInfo);
1221 LogDebug("didChangeProgressCallback progress = " << *progress);
1224 void ViewLogic::loadProgressFinishedCallback(
1226 Evas_Object* /*obj*/,
1227 void* /*eventInfo*/)
1229 LogDebug("didFinishProgressCallback");
1231 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1232 if (!view->m_cbs->progressFinish.empty()) {
1233 view->m_cbs->progressFinish();
1237 void ViewLogic::processCrashedCallback(
1239 Evas_Object* /*obj*/,
1242 LogInfo("processCrashedCallback");
1244 ViewLogic const * const view =
1245 static_cast<ViewLogic const * const>(data);
1246 if (!view->m_cbs->webCrash.empty()) {
1247 view->m_cbs->webCrash();
1249 // This flag will be prevented exit() call in the Webkit side
1250 if (NULL != eventInfo) {
1251 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1255 void ViewLogic::createWindowCallback(
1260 LogDebug("createWindowCallback");
1262 ViewLogic* This = static_cast<ViewLogic*>(data);
1264 // First, current webview should be handled by user callback
1265 if (!This->m_cbs->bufferUnset.empty()) {
1266 This->m_cbs->bufferUnset(obj);
1269 // this can be set by executable for specific purpose
1270 Evas* canvas = NULL;
1271 if (!This->m_cbs->windowCreateBefore.empty()) {
1272 // 'obj' is parent webview object
1273 This->m_cbs->windowCreateBefore(&canvas, obj);
1276 canvas = evas_object_evas_get(This->m_window);
1279 // create new ewkview
1280 This->createEwkView(canvas);
1281 Evas_Object* newEwkView = This->m_currentEwkView;
1283 // initialize new ewkview
1284 This->setStartPage();
1285 This->ewkClientInit(newEwkView);
1286 This->prepareEwkView(newEwkView);
1288 // Specific jobs of child, parent webview are handled by each executable
1289 if (!This->m_cbs->windowCreateAfter.empty()) {
1290 // 'obj' is parent webview, 'newEwkView' is child webview
1291 This->m_cbs->windowCreateAfter(obj, newEwkView);
1294 // Lastly, new webview should be handled by user callback
1295 if (!This->m_cbs->bufferSet.empty()) {
1296 This->m_cbs->bufferSet(newEwkView);
1298 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1301 void ViewLogic::closeWindowCallback(
1304 void* /*eventInfo*/)
1306 LogDebug("closeWindowCallback");
1307 ViewLogic* This = static_cast<ViewLogic*>(data);
1308 This->m_closedEwkView = obj;
1309 ecore_idler_add(windowCloseIdlerCallback, This);
1312 void ViewLogic::policyNavigationDecideCallback(
1314 Evas_Object* /*obj*/,
1317 LogDebug("policyNavigationDecideCallback called");
1319 ViewLogic* This = static_cast<ViewLogic*>(data);
1321 Ewk_Policy_Decision* policyDecision =
1322 static_cast<Ewk_Policy_Decision*>(eventInfo);
1324 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1328 This->m_currentEwkView))
1331 ewk_policy_decision_use(policyDecision);
1333 // check whether this is new empty window
1334 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1335 if(!activeUrl || 0 == strlen(activeUrl)) {
1337 * The view is empty and scheme has been handled externally. When
1338 * user gets back from the external application he'd see blank page
1339 * and won't be able to navigate back. This happens when window.open
1340 * is used to handle schemes like sms/mms/mailto (for example in
1341 * WAC web standards tests: WS-15XX).
1343 * To solve the problem, the empty view is removed from the stack
1344 * and the previous one is shown. This is not an elegant solution
1345 * but we don't have a better one.
1347 LogInfo("Scheme has been handled externally. Removing empty view.");
1348 if (ewk_view_back_possible(This->m_currentEwkView)) {
1349 // go back to previous WKPage
1350 ewk_view_back(This->m_currentEwkView);
1352 // stop current WKPage
1353 ewk_view_stop(This->m_currentEwkView);
1354 ecore_idler_add(windowCloseIdlerCallback, This);
1359 ewk_policy_decision_ignore(policyDecision);
1363 void ViewLogic::policyNewWindowDecideCallback(
1365 Evas_Object* /*obj*/,
1368 LogDebug("policyNewWindowDecideCallback called");
1370 ViewLogic* This = static_cast<ViewLogic*>(data);
1372 Ewk_Policy_Decision* policyDecision =
1373 static_cast<Ewk_Policy_Decision*>(eventInfo);
1375 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1379 This->m_currentEwkView))
1381 ewk_policy_decision_use(policyDecision);
1384 ewk_policy_decision_ignore(policyDecision);
1388 void ViewLogic::pageResponseDecideCallback(
1390 Evas_Object* /*obj*/,
1393 LogDebug("pageResponseDecideCallback called");
1395 ViewLogic* This = static_cast<ViewLogic*>(data);
1397 Ewk_Policy_Decision* policyDecision =
1398 static_cast<Ewk_Policy_Decision*>(eventInfo);
1399 Ewk_Policy_Decision_Type policyDecisionType =
1400 ewk_policy_decision_type_get(policyDecision);
1402 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1404 ewk_policy_decision_use(policyDecision);
1405 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1406 LogDebug("download");
1407 ewk_policy_decision_suspend(policyDecision);
1409 // get uri information
1410 const char* url = ewk_policy_decision_url_get(policyDecision);
1411 if (NULL == url || strlen(url) == 0) {
1412 LogDebug("url data is empty");
1413 ewk_policy_decision_use(policyDecision);
1416 LogDebug("url = [" << url << "]");
1418 // get content information
1419 const char* content =
1420 ewk_policy_decision_response_mime_get(policyDecision);
1421 LogDebug("content type = [" << content << "]");
1423 // get cookie information
1424 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1425 LogDebug("cookie = [" << cookie << "]");
1427 LogDebug("Content not supported, will be opened in external app");
1428 This->m_appsSupport->downloadRequest(
1432 ewk_policy_decision_ignore(policyDecision);
1433 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1435 ewk_policy_decision_ignore(policyDecision);
1437 LogDebug("Type isn't handled");
1438 ewk_policy_decision_ignore(policyDecision);
1442 void ViewLogic::contextmenuCustomizeCallback(
1444 Evas_Object* /*obj*/,
1447 LogDebug("contextmenuCustomizeCallback called");
1450 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1451 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1452 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1453 (This->m_model->SettingList.Get().getContextMenu()
1454 == ContextMenu_Disable))
1456 LogDebug("ContextMenu Disable!!");
1457 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1458 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1460 ewk_context_menu_item_remove(menu, item);
1463 LogDebug("ContextMenu Enable!!");
1464 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1465 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1467 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1470 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1471 ewk_context_menu_item_remove(menu, item);
1474 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1475 ewk_context_menu_item_remove(menu, item);
1486 void ViewLogic::formSubmitCallback(
1488 Evas_Object* /*obj*/,
1491 LogDebug("formSubmitCallback called");
1493 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1495 const char* uri = ewk_form_data_url_get(formData);
1497 LogError("URL is empty");
1501 Eina_Hash* userData = ewk_form_data_values_get(formData);
1502 ViewModule::PasswordSupport::submitClicked(uri, userData);
1505 void ViewLogic::geolocationPermissionRequestCallback(
1507 Evas_Object* /*obj*/,
1511 ViewLogic* This = static_cast<ViewLogic*>(data);
1513 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1515 This->m_securityOriginSupport->getSecurityOriginDAO(),
1519 void ViewLogic::notificationShowCallback(
1521 Evas_Object* /*obj*/,
1524 LogDebug("notificationShowCallback called");
1526 ViewLogic* This = static_cast<ViewLogic*>(data);
1529 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1531 using namespace ViewModule::WebNotification;
1533 WebNotificationDataPtr notiData(
1534 new WebNotificationData(
1536 ewk_notification_id_get(noti)));
1538 DPL::OptionalString string =
1539 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1540 if (!string.IsNull()) {
1541 notiData->m_iconURL = DPL::ToUTF8String(*string);
1543 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1544 if (!string.IsNull()) {
1545 notiData->m_title = DPL::ToUTF8String(*string);
1547 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1548 if (!string.IsNull()) {
1549 notiData->m_body = DPL::ToUTF8String(*string);
1552 LogInfo("notification id : " << notiData->m_id);
1553 LogInfo("notification iconURL : " << notiData->m_iconURL);
1554 LogInfo("notification title : " << notiData->m_title);
1555 LogInfo("notification body : " << notiData->m_body);
1557 showWebNotification(notiData);
1558 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1561 void ViewLogic::notificationCancelCallback(
1563 Evas_Object* /*obj*/,
1564 void* /*eventInfo*/)
1566 LogDebug("notificationCancelCallback called");
1569 void ViewLogic::notificationPermissionRequestCallback(
1571 Evas_Object* /*obj*/,
1574 LogDebug("notificationPermissionRequestCallback called");
1576 ViewLogic* This = static_cast<ViewLogic*>(data);
1579 Ewk_Notification_Permission_Request* request =
1580 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1581 ewk_notification_permission_request_response(
1588 void ViewLogic::vibrationVibrateCallback(
1590 Evas_Object* /*obj*/,
1593 LogDebug("vibrationVibrateCallback called");
1595 ViewLogic* This = static_cast<ViewLogic*>(data);
1598 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1601 // This->m_vibrationSupport->startVibration(vibrationTime);
1606 void ViewLogic::vibrationCancelCallback(
1608 Evas_Object* /*obj*/,
1609 void* /*eventInfo*/)
1611 LogDebug("vibrationCancelCallback called");
1613 ViewLogic* This = static_cast<ViewLogic*>(data);
1616 // This->m_vibrationSupport->stopVibration();
1621 // EWK Orientation Callback
1622 Eina_Bool ViewLogic::orientationLockCallback(
1624 Eina_Bool /*needLock*/,
1628 LogDebug("orientationLockCallback called");
1630 ViewLogic* This = static_cast<ViewLogic*>(data);
1632 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1633 LogDebug("orientation is portrait-primary");
1634 elm_win_rotation_with_resize_set(This->m_window, 0);
1635 ewk_view_orientation_send(obj, 0);
1636 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1637 LogDebug("orientation is landscape-primary");
1638 elm_win_rotation_with_resize_set(This->m_window, 270);
1639 ewk_view_orientation_send(obj, 90);
1640 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1641 LogDebug("orientation is portrait-secondary");
1642 elm_win_rotation_with_resize_set(This->m_window, 180);
1643 ewk_view_orientation_send(obj, 180);
1644 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1645 LogDebug("orientation is landscape-secondary");
1646 elm_win_rotation_with_resize_set(This->m_window, 90);
1647 ewk_view_orientation_send(obj, -90);
1649 LogDebug("Wrong orientation is set");
1656 // Fullscreen API callbacks
1657 void ViewLogic::enterFullscreenCallback(
1659 Evas_Object* /*obj*/,
1660 void* /*eventInfo*/)
1662 LogInfo("enterFullscreenCallback called");
1664 ViewLogic* This = static_cast<ViewLogic*>(data);
1665 if (!This->m_cbs->toggleFullscreen.empty()) {
1666 This->m_cbs->toggleFullscreen(true);
1669 void ViewLogic::exitFullscreenCallback(
1671 Evas_Object* /*obj*/,
1672 void* /*eventInfo*/)
1674 LogInfo("exitFullscreenCallback called");
1676 ViewLogic* This = static_cast<ViewLogic*>(data);
1677 if (!This->m_cbs->toggleFullscreen.empty()) {
1678 This->m_cbs->toggleFullscreen(false);
1682 void ViewLogic::imeChangedCallback(
1684 Evas_Object* /*obj*/,
1690 ViewLogic* This = static_cast<ViewLogic*>(data);
1691 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1692 This->m_imeWidth = rect->w;
1693 This->m_imeHeight = rect->h;
1696 void ViewLogic::imeOpenedCallback(
1698 Evas_Object* /*obj*/,
1699 void* /*eventInfo*/)
1703 ViewLogic* This = static_cast<ViewLogic*>(data);
1705 using namespace WrtPlugins::W3C;
1706 SoftKeyboardChangeArgs args;
1707 args.state = IME_STATE_ON;
1708 args.width = This->m_imeWidth;
1709 args.height = This->m_imeHeight;
1710 This->fireJavascriptEvent(
1711 static_cast<int>(SoftKeyboardChangeCustomEvent),
1715 void ViewLogic::imeClosedCallback(
1717 Evas_Object* /*obj*/,
1718 void* /*eventInfo*/)
1722 ViewLogic* This = static_cast<ViewLogic*>(data);
1724 using namespace WrtPlugins::W3C;
1725 SoftKeyboardChangeArgs args;
1726 args.state = IME_STATE_OFF;
1728 This->fireJavascriptEvent(
1729 static_cast<int>(SoftKeyboardChangeCustomEvent),
1733 void ViewLogic::usermediaPermissionRequestCallback(
1735 Evas_Object* /*obj*/,
1738 LogDebug("usermediaPermissionRequestCallback called");
1740 ViewLogic* This = static_cast<ViewLogic*>(data);
1741 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1747 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1750 Ewk_Custom_Handlers_Data* handler =
1751 static_cast<Ewk_Custom_Handlers_Data*>(data);
1752 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1753 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1755 LogDebug("base url: " << base_url);
1756 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1758 const char* url = ewk_custom_handlers_data_url_get(handler);
1760 LogDebug("url: " << url);
1761 customHandler->url = DPL::FromASCIIString(string(url));
1763 const char* target = ewk_custom_handlers_data_target_get(handler);
1765 LogDebug("target: " << target);
1766 customHandler->target = DPL::FromASCIIString(string(target));
1768 const char* title = ewk_custom_handlers_data_title_get(handler);
1770 LogDebug("title: " << title);
1771 customHandler->title = DPL::FromASCIIString(string(title));
1773 return customHandler;
1776 void ViewLogic::attachToCustomHandlersDao()
1778 if (!m_attachedToCustomHandlerDao) {
1779 CustomHandlerDB::Interface::attachDatabaseRW();
1783 void ViewLogic::detachFromCustomHandlersDao()
1785 if (m_attachedToCustomHandlerDao) {
1786 CustomHandlerDB::Interface::detachDatabase();
1790 const int protocolWhiteListLenth = 15;
1791 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1809 const int contentBlackListLenth = 14;
1810 char const * const contentBlackList[contentBlackListLenth] = {
1811 "application/x-www-form-urlencoded",
1812 "application/xhtml+xml",
1818 "multipart/x-mixed-replace",
1819 "text/cache-manifest",
1828 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1831 * @param customHandler
1833 void saveUserResponse(Wrt::Popup::PopupResponse response,
1834 CustomHandlerDB::CustomHandlerPtr customHandler)
1837 case Wrt::Popup::YES_DO_REMEMBER:
1838 LogDebug("User allowed, remember");
1839 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1840 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1842 case Wrt::Popup::YES_DONT_REMEMBER:
1843 LogDebug("User allowed, don't remember");
1844 customHandler->user_decision = CustomHandlerDB::Agreed;
1846 case Wrt::Popup::NO_DO_REMEMBER:
1847 LogDebug("User didn't allow, remember");
1848 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1849 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1851 case Wrt::Popup::NO_DONT_REMEMBER:
1852 LogDebug("User didn't allow, don't remember");
1853 customHandler->user_decision = CustomHandlerDB::Declined;
1858 //TODO registration, checking if registered and unregistration can be done in
1859 //common functions for both types of handlers. Only white and black lists
1860 //have to be separated
1861 //TODO attach database only one at the start (not in every callback?)
1862 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1868 CustomHandlerDB::CustomHandlerPtr customHandler =
1869 getCustomHandlerFromData(eventInfo);
1871 std::string scheme = DPL::ToUTF8String(customHandler->target);
1872 if (scheme.empty()) {
1873 LogError("No scheme provided");
1874 //TODO what about securityError?
1877 bool matched = false;
1878 //scheme on whiteList
1879 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1880 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1882 LogDebug("Match found, protocol can be handled");
1887 //starts with web+ and have at least 5 chars (lowercase ASCII)
1888 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1889 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1890 //throw SecurityException
1897 if (c < 'a' || c > 'z') {
1898 LogWarning("Wrong char inside scheme. "
1899 << "Only lowercase ASCII letters accepted");
1900 //throw SecurityException
1907 ViewLogic* This = static_cast<ViewLogic*>(data);
1908 LogDebug("Creating handlers dao");
1909 This->attachToCustomHandlersDao();
1910 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1911 CustomHandlerDB::CustomHandlerPtr handler =
1912 handlersDao.getProtocolHandler(customHandler->target,
1914 customHandler->base_url);
1915 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1916 LogDebug("Protocol already registered - nothing to do");
1918 LogDebug("Protocol handler not found");
1919 Wrt::Popup::PopupResponse response =
1920 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1921 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1922 PROTOCOL_HANDLER_ASK_TITLE,
1923 PROTOCOL_HANDLER_ASK_MSG,
1924 PROTOCOL_HANDLER_ASK_REMEMBER);
1925 saveUserResponse(response, customHandler);
1926 if (customHandler->user_decision == CustomHandlerDB::Declined)
1928 handlersDao.registerProtocolHandler(*(customHandler.get()));
1929 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1930 //TODO remove old default handler somehow from appsvc
1931 LogDebug("Registering appservice entry");
1932 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1934 DPL::ToUTF8String(customHandler->target).c_str(),
1935 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1936 if (APPSVC_RET_OK != ret)
1938 LogWarning("Appsvc entry failed: " << ret);
1941 LogDebug("Protocal saved");
1944 This->detachFromCustomHandlersDao();
1947 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1952 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1953 ViewLogic* This = static_cast<ViewLogic*>(data);
1954 LogDebug("Creating handlers dao");
1955 This->attachToCustomHandlersDao();
1956 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1957 CustomHandlerDB::CustomHandlerPtr handler =
1958 handlersDao.getProtocolHandler(customHandler->target,
1960 customHandler->base_url);
1962 if (handler->user_decision & CustomHandlerDB::Agreed)
1963 ewk_custom_handlers_data_result_set(
1964 static_cast<Ewk_Custom_Handlers_Data*>(data),
1965 EWK_CUSTOM_HANDLERS_REGISTERED);
1967 ewk_custom_handlers_data_result_set(
1968 static_cast<Ewk_Custom_Handlers_Data*>(data),
1969 EWK_CUSTOM_HANDLERS_DECLINED);
1971 ewk_custom_handlers_data_result_set(
1972 static_cast<Ewk_Custom_Handlers_Data*>(data),
1973 EWK_CUSTOM_HANDLERS_NEW);
1974 This->detachFromCustomHandlersDao();
1977 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1982 CustomHandlerDB::CustomHandlerPtr customHandler =
1983 getCustomHandlerFromData(eventInfo);
1984 ViewLogic* This = static_cast<ViewLogic*>(data);
1985 LogDebug("Creating handlers dao");
1986 This->attachToCustomHandlersDao();
1987 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1988 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1989 handlersDao.getProtocolHandler(customHandler->target,
1991 customHandler->base_url);
1993 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1994 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1996 handlersDao.unregisterProtocolHandler(customHandler->target,
1998 customHandler->base_url);
2000 LogDebug("Nothing to unregister");
2002 This->detachFromCustomHandlersDao();
2005 void ViewLogic::contentHandlerRegistrationCallback(void* data,
2011 CustomHandlerDB::CustomHandlerPtr customHandler =
2012 getCustomHandlerFromData(eventInfo);
2014 std::string mimeType = DPL::ToUTF8String(customHandler->target);
2015 if (mimeType.empty()) {
2016 LogError("No mimeType provided.");
2019 for (int i = 0; i < contentBlackListLenth; ++i)
2021 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
2023 LogWarning("mimeType blacklisted");
2024 //throw SecurityException
2029 ViewLogic* This = static_cast<ViewLogic*>(data);
2030 LogDebug("Creating handlers dao");
2031 This->attachToCustomHandlersDao();
2032 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2033 CustomHandlerDB::CustomHandlerPtr handler =
2034 handlersDao.getContentHandler(customHandler->target,
2036 customHandler->base_url);
2037 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
2038 LogDebug("Protocol already registered - nothing to do");
2040 LogDebug("Protocol handler not found");
2041 Wrt::Popup::PopupResponse response =
2042 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
2043 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
2044 CONTENT_HANDLER_ASK_TITLE,
2045 CONTENT_HANDLER_ASK_MSG,
2046 CONTENT_HANDLER_AKS_REMEMBER);
2047 saveUserResponse(response, customHandler);
2048 if (customHandler->user_decision == CustomHandlerDB::Declined)
2050 handlersDao.registerContentHandler(*(customHandler.get()));
2051 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
2052 //TODO remove old default handler somehow from appsvc
2053 LogDebug("Registering appservice entry");
2054 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
2055 DPL::ToUTF8String(customHandler->target).c_str(),
2057 DPL::ToUTF8String(This->m_model->TizenId).c_str());
2058 if (APPSVC_RET_OK != ret)
2060 LogWarning("Appsvc entry failed: " << ret);
2063 LogDebug("Content saved");
2065 This->detachFromCustomHandlersDao();
2068 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
2073 CustomHandlerDB::CustomHandlerPtr customHandler =
2074 getCustomHandlerFromData(eventInfo);
2075 ViewLogic* This = static_cast<ViewLogic*>(data);
2076 LogDebug("Creating handlers dao");
2078 This->attachToCustomHandlersDao();
2079 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2080 CustomHandlerDB::CustomHandlerPtr handler =
2081 handlersDao.getContentHandler(customHandler->target,
2083 customHandler->base_url);
2085 if (handler->user_decision & CustomHandlerDB::Agreed)
2086 ewk_custom_handlers_data_result_set(
2087 static_cast<Ewk_Custom_Handlers_Data*>(data),
2088 EWK_CUSTOM_HANDLERS_REGISTERED);
2090 ewk_custom_handlers_data_result_set(
2091 static_cast<Ewk_Custom_Handlers_Data*>(data),
2092 EWK_CUSTOM_HANDLERS_DECLINED);
2094 ewk_custom_handlers_data_result_set(
2095 static_cast<Ewk_Custom_Handlers_Data*>(data),
2096 EWK_CUSTOM_HANDLERS_NEW);
2097 This->detachFromCustomHandlersDao();
2100 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
2105 CustomHandlerDB::CustomHandlerPtr customHandler =
2106 getCustomHandlerFromData(eventInfo);
2107 ViewLogic* This = static_cast<ViewLogic*>(data);
2108 LogDebug("Creating handlers dao");
2109 This->attachToCustomHandlersDao();
2110 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2111 CustomHandlerDB::CustomHandlerPtr handlerCheck =
2112 handlersDao.getContentHandler(customHandler->target,
2114 customHandler->base_url);
2116 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2117 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2119 handlersDao.unregisterContentHandler(customHandler->target,
2121 customHandler->base_url);
2123 LogDebug("Nothing to unregister");
2124 This->detachFromCustomHandlersDao();
2127 void ViewLogic::didRunJavaScriptCallback(
2128 Evas_Object* /*obj*/,
2132 LogInfo("didRunJavaScriptCallback called");
2133 LogInfo("result = " << result);
2136 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
2138 LogDebug("closeIdlerCallback");
2139 ViewLogic* This = static_cast<ViewLogic*>(data);
2140 This->windowClose();
2141 return ECORE_CALLBACK_CANCEL;
2144 int ViewLogic::appcoreLowMemoryCallback(void *data)
2146 LogInfo("appcoreLowMemoryCallback");
2148 ViewLogic* This = static_cast<ViewLogic*>(data);
2150 if (NULL == This->m_ewkContext) {
2151 LogInfo("ewk isn't initialize at this moment");
2153 // Crash may occur on specific situation
2154 // So use the followings after they become stable
2155 //ewk_context_cache_clear(This->m_ewkContext);
2156 //ewk_context_notify_low_memory(This->m_ewkContext);
2162 void ViewLogic::databaseUsagePermissionRequestCallback(
2164 Evas_Object* /*obj*/,
2167 LogDebug("databaseUsagePermissionRequestCallback called");
2169 ViewLogic* This = static_cast<ViewLogic*>(data);
2172 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
2174 This->m_securityOriginSupport->getSecurityOriginDAO(),
2179 void ViewLogic::fileSystemPermissionRequestCallback(
2181 Evas_Object* /*obj*/,
2184 LogDebug("fileSystemPermissionRequestCallback called");
2186 ViewLogic* This = static_cast<ViewLogic*>(data);
2188 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
2190 This->m_securityOriginSupport->getSecurityOriginDAO(),
2194 void ViewLogic::didRecieveMessageFromInjectedBundle(
2196 const char* /*body*/)
2198 LogDebug("did recive message " << name);
2201 void ViewLogic::didReceiveSynchronousMessage(
2206 LogDebug("didReceiveSynchronousMessage called");
2211 LogDebug("body is empty");
2215 if (!strcmp(name, uriBlockedMessageName)) {
2216 LogDebug("received : " << uriBlockedMessageName);
2217 // Currently WebProcess informs obly about blocked
2218 // URI - URI localization and security chekcs are
2219 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2220 // and bundle_uri_handling.cpp)
2221 rememberBlockedURI(DPL::FromUTF8String(body));
2223 } else if (!strcmp(name, uriChangedMessageName)) {
2224 LogDebug("received : " << uriChangedMessageName);
2225 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2226 *returnData = strdup(ret.c_str());
2230 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2232 m_blockedUri = DPL::ToUTF8String(inputURI);
2233 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2237 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2239 using namespace ViewModule::SecuritySupport;
2241 std::string url = DPL::ToUTF8String(changedURL);
2242 LogInfo("URL = [" << url << "]");
2245 // If url is same to URICHANGE_BLOCKED_URL,
2246 // this url has been already blocked by willsend.
2247 // So current page should be moved to previous page
2248 if (url == URICHANGE_BLOCKED_URL)
2250 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2252 // block this page and open it in browser
2253 LogDebug("Request was blocked by WARP: " << url.c_str());
2254 if (!m_blockedUri.empty()) {
2255 LogDebug("open browser : " << m_blockedUri);
2256 bundle* bundleData = bundle_create();
2257 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2258 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2259 CONTROLLER_POST_EVENT(
2260 ApplicationLauncher,
2261 ApplicationLauncherEvents::LaunchApplicationByAppService(
2265 m_blockedUri = std::string();
2268 if (ewk_view_back_possible(m_currentEwkView)) {
2269 // go back to previous page
2270 ewk_view_back(m_currentEwkView);
2272 // stop current page
2273 ewk_view_stop(m_currentEwkView);
2274 ecore_idler_add(windowCloseIdlerCallback, this);
2277 // This is used in case of returning previous page
2279 return URICHANGE_PLUGIN_NO_CHANGE;
2284 // Check if this url with 'http' or 'https' is included in whitelist,
2285 // which has lists of accessible external documents and
2286 // used for ONLY Tizen app
2287 std::string matchedScheme;
2288 std::string matchedUri;
2289 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2292 ViewModule::Scheme scheme(matchedScheme);
2293 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2294 scheme.GetType() == ViewModule::Scheme::HTTPS)
2296 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2297 if (!checkWhitelist(url.c_str())) {
2298 LogInfo("This uri is not included in white document list");
2299 return URICHANGE_PLUGIN_STOP_ONLY;
2301 LogInfo("This url is included in WhiteList");
2303 // For WAC app, WRT should block access of device api
2304 // for external documents
2305 return URICHANGE_PLUGIN_STOP_ONLY;
2309 // register javascript object for plugins to be used
2310 LogInfo("Register Plugin Objects");
2311 return URICHANGE_PLUGIN_RESTART;
2314 void ViewLogic::windowClose()
2316 LogDebug("windowClose");
2317 Assert(m_closedEwkView && "no closed webview");
2319 if (1 >= m_ewkViewList.size()) {
2320 if (!m_cbs->webkitExit.empty()) {
2321 m_cbs->webkitExit();
2324 // call user callbacks
2325 if (!m_cbs->bufferUnset.empty()) {
2326 m_cbs->bufferUnset(m_currentEwkView);
2328 if (!m_cbs->windowClose.empty()) {
2329 m_cbs->windowClose(m_closedEwkView);
2331 removeEwkView(m_closedEwkView);
2333 // get latest ewkView
2334 m_currentEwkView = m_ewkViewList.back();
2335 const char* uri = ewk_view_url_get(m_currentEwkView);
2336 if (NULL == uri || 0 == strlen(uri)) {
2337 m_currentUri.clear();
2343 /* In case we support many pages in parallel
2344 then view is not suspended*/
2345 //resumeEwkView(m_currentEwkView);
2348 if (!m_cbs->bufferSet.empty()) {
2349 m_cbs->bufferSet(m_currentEwkView);