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 <view_logic_scheme_support.h>
53 #include <view_logic_filesystem_support.h>
54 #include <view_logic_geolocation_support_webkit2.h>
55 #include <view_logic_usermedia_support.h>
56 #include <view_logic_web_notification_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_activate(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::reloadStartPage()
383 LogInfo("Reload Start Page");
384 // prevent fail to load plugin bundle side
385 m_isBackgroundReload = true;
386 PluginModuleSupport::resume(m_ewkContext);
388 if (m_ewkViewList.size() != 0) {
389 while (m_ewkViewList.size() > 0) {
390 if (!m_cbs->bufferUnset.empty()) {
391 m_cbs->bufferUnset(m_currentEwkView);
393 removeEwkView(m_currentEwkView);
397 // create new webview
398 createEwkView(evas_object_evas_get(m_window));
399 ewkClientInit(m_currentEwkView);
402 prepareEwkView(m_currentEwkView);
403 initializePluginLoading();
406 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
409 if (!m_cbs->bufferSet.empty()) {
410 m_cbs->bufferSet(m_currentEwkView);
412 LogInfo("Reloading Start Page is done!");
415 Evas_Object* ViewLogic::getCurrentWebview()
417 LogInfo("get current webview");
418 return m_currentEwkView;
421 void ViewLogic::fireJavascriptEvent(int event, void* data)
423 PluginModuleSupport::dispatchJavaScriptEvent(
425 static_cast<WrtPlugins::W3C::CustomEventType>(event),
429 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
434 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
436 LogInfo("initializeEwkContext called");
437 Assert(newEwkContext && "Ewk_Context provided can not be null");
438 // bundle callback setting
439 ewk_context_message_from_injected_bundle_callback_set(
441 contextMessageFromInjectedBundleCallback,
442 static_cast<void*>(this));
444 // proxy server setting
445 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
446 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
447 || (strstr(proxyAddress, "0.0.0.0")))
449 LogInfo("proxy address is empty");
450 ewk_context_proxy_uri_set(newEwkContext, NULL);
452 LogInfo("proxy address [" << proxyAddress << "]");
453 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
462 const char *theme = elm_theme_get(NULL);
465 LogInfo("theme is " << m_theme);
468 // Ewk download callback (WKContextDownloadClient)
469 ewk_context_did_start_download_callback_set(
471 didStartDownloadCallback,
474 // set to member value
475 m_ewkContext = newEwkContext;
478 void ViewLogic::finalizeEwkContext()
480 LogInfo("finalizeEwkContext called");
481 ewk_context_message_from_injected_bundle_callback_set(
485 // ewk_context_delete(m_ewkContext);
489 void ViewLogic::initializeSupport()
491 // set local stroage database path
492 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
493 ewk_context_web_storage_path_set(m_ewkContext,
494 dao.getPrivateLocalStoragePath().c_str());
495 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
496 ViewModule::StorageSupport::initializeStorage(m_model);
497 m_appsSupport->initialize(m_model);
498 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
501 // m_vibrationSupport->initialize();
504 void ViewLogic::initializePluginLoading()
506 // inform wrt information for plugin loading to web process
507 PluginModuleSupport::start(
510 elm_config_scale_get(),
511 ApplicationDataSingleton::Instance().getEncodedBundle(),
513 m_model->SettingList.Get().isEncrypted());
516 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
517 Assert(NULL != wkView && "ewk_view not created at this point");
518 // WKPageLoaderClient
519 evas_object_smart_callback_add(
524 evas_object_smart_callback_add(
527 loadFinishedCallback,
529 evas_object_smart_callback_add(
532 titleChangedCallback,
534 evas_object_smart_callback_add(
537 loadProgressCallback,
539 evas_object_smart_callback_add(
541 EWK_LOAD_PROGRESS_FINISHED,
542 loadProgressFinishedCallback,
544 evas_object_smart_callback_add(
547 processCrashedCallback,
551 evas_object_smart_callback_add(
554 createWindowCallback,
556 evas_object_smart_callback_add(
562 // WKPagePolicyClient
563 evas_object_smart_callback_add(
565 EWK_POLICY_NAVIGATION_DECIDE,
566 policyNavigationDecideCallback,
568 evas_object_smart_callback_add(
570 EWK_POLICY_NEWWINDOW_DECIDE,
571 policyNewWindowDecideCallback,
573 evas_object_smart_callback_add(
575 EWK_POLICY_RESPONSE_DECIDE,
576 pageResponseDecideCallback,
579 // WKPageContextMenuClient
580 evas_object_smart_callback_add(
582 EWK_CONTEXTMENU_CUSTOMIZE,
583 contextmenuCustomizeCallback,
587 evas_object_smart_callback_add(
593 // EWK Geolocation Callback
594 evas_object_smart_callback_add(
596 EWK_REQUEST_GEOLOCATION_PERMISSION,
597 geolocationPermissionRequestCallback,
600 // EWK Notification Callback
601 evas_object_smart_callback_add(
603 EWK_NOTIFICATION_SHOW,
604 notificationShowCallback,
606 evas_object_smart_callback_add(
608 EWK_NOTIFICATION_CANCEL,
609 notificationCancelCallback,
611 evas_object_smart_callback_add(
613 EWK_NOTIFICATION_PERMISSION_REQUEST,
614 notificationPermissionRequestCallback,
617 // EWK Vibration Callback
618 evas_object_smart_callback_add(
620 EWK_VIBRATION_VIBRATE,
621 vibrationVibrateCallback,
623 evas_object_smart_callback_add(
625 EWK_VIBRATION_CANCEL,
626 vibrationCancelCallback,
628 evas_object_smart_callback_add(
630 EWK_CONTEXT_EXCEEDED_QUOATA,
631 databaseUsagePermissionRequestCallback,
633 evas_object_smart_callback_add(
635 EWK_FILESYSTEM_PERMISSION_REQUEST,
636 fileSystemPermissionRequestCallback,
639 // EWK Orientation Callback
640 //ewk_view_orientation_lock_callback_set(
642 // orientationLockCallback,
645 // Fullscreen API callbacks
646 evas_object_smart_callback_add(
648 EWK_FULLSCREEN_ENTER,
649 enterFullscreenCallback,
651 evas_object_smart_callback_add(
654 exitFullscreenCallback,
658 // when ime start to be showed on the webview,
659 // this callback will be called
660 evas_object_smart_callback_add(
662 EWK_INPUTMETHOD_CHANGED,
666 // this callback will be called
667 // when ime finishes to be showed on the webview
668 // "event_info" arg of this callback is always NULL point
669 // if web content should know size of ime,
670 // use "inputmethod,changed" instead of this.
672 evas_object_smart_callback_add(
674 EWK_EDITORCLIENT_IME_OPENED,
678 // when ime finished to be hidden,
679 // this callback will be called
680 evas_object_smart_callback_add(
682 EWK_EDITORCLIENT_IME_CLOSED,
686 // usermedia callback
687 evas_object_smart_callback_add(
689 EWK_USERMEDIA_PERMISSION_REQUEST,
690 usermediaPermissionRequestCallback,
693 // custom content/scheme handlers
694 evas_object_smart_callback_add(
696 EWK_PROTOCOLHANDLER_REGISTRATION,
697 protocolHandlerRegistrationCallback,
699 evas_object_smart_callback_add(
701 EWK_PROTOCOLHANDLER_ISREGISTERED,
702 protocolHandlerIsRegisteredCallback,
704 evas_object_smart_callback_add(
706 EWK_PROTOCOLHANDLER_UNREGISTRATION,
707 protocolHandlerUnregistrationCallback,
710 evas_object_smart_callback_add(
712 EWK_CONTENTHANDLER_REGISTRATION,
713 contentHandlerRegistrationCallback,
715 evas_object_smart_callback_add(
717 EWK_CONTENTHANDLER_ISREGISTERED,
718 contentHandlerIsRegisteredCallback,
720 evas_object_smart_callback_add(
722 EWK_CONTENTHANDLER_UNREGISTRATION,
723 contentHandlerUnregistrationCallback,
727 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
728 LogDebug("ewkClientDeinit");
729 Assert(NULL != wkView && "ewk_view not created at this point");
731 // WKPageLoaderClient
732 evas_object_smart_callback_del(
735 loadStartedCallback);
736 evas_object_smart_callback_del(
739 loadFinishedCallback);
740 evas_object_smart_callback_del(
743 titleChangedCallback);
744 evas_object_smart_callback_del(
747 loadProgressCallback);
748 evas_object_smart_callback_del(
750 EWK_LOAD_PROGRESS_FINISHED,
751 loadProgressFinishedCallback);
752 evas_object_smart_callback_del(
755 loadProgressCallback);
758 evas_object_smart_callback_del(
761 createWindowCallback);
762 evas_object_smart_callback_del(
765 closeWindowCallback);
767 // WKPagePolicyClient
768 evas_object_smart_callback_del(
770 EWK_POLICY_NAVIGATION_DECIDE,
771 policyNavigationDecideCallback);
772 evas_object_smart_callback_del(
774 EWK_POLICY_NEWWINDOW_DECIDE,
775 policyNewWindowDecideCallback);
776 evas_object_smart_callback_del(
778 EWK_POLICY_RESPONSE_DECIDE,
779 pageResponseDecideCallback);
781 // WKPageContextMenuClient
782 evas_object_smart_callback_del(
784 EWK_CONTEXTMENU_CUSTOMIZE,
785 contextmenuCustomizeCallback);
788 evas_object_smart_callback_del(
793 // EWK Geolocation Callback
794 evas_object_smart_callback_del(
796 EWK_REQUEST_GEOLOCATION_PERMISSION,
797 geolocationPermissionRequestCallback);
799 // EWK Notification Callback
800 evas_object_smart_callback_del(
802 EWK_NOTIFICATION_SHOW,
803 notificationShowCallback);
804 evas_object_smart_callback_del(
806 EWK_NOTIFICATION_CANCEL,
807 notificationCancelCallback);
808 evas_object_smart_callback_del(
810 EWK_NOTIFICATION_PERMISSION_REQUEST,
811 notificationPermissionRequestCallback);
813 // EWK Vibration Callback
814 evas_object_smart_callback_del(
816 EWK_VIBRATION_VIBRATE,
817 vibrationVibrateCallback);
818 evas_object_smart_callback_del(
820 EWK_VIBRATION_CANCEL,
821 vibrationCancelCallback);
823 evas_object_smart_callback_del(
825 EWK_CONTEXT_EXCEEDED_QUOATA,
826 databaseUsagePermissionRequestCallback);
827 evas_object_smart_callback_del(
829 EWK_FILESYSTEM_PERMISSION_REQUEST,
830 fileSystemPermissionRequestCallback);
832 // EWK Orientation Callback
833 //ewk_view_orientation_lock_callback_set(
838 // ime change/show/hide callback
839 evas_object_smart_callback_del(
841 EWK_INPUTMETHOD_CHANGED,
843 evas_object_smart_callback_del(
845 EWK_EDITORCLIENT_IME_OPENED,
847 evas_object_smart_callback_del(
849 EWK_EDITORCLIENT_IME_CLOSED,
852 // usermedia callback
853 evas_object_smart_callback_del(
855 EWK_USERMEDIA_PERMISSION_REQUEST,
856 usermediaPermissionRequestCallback);
858 // custom content/scheme handlers
859 evas_object_smart_callback_del(
861 EWK_PROTOCOLHANDLER_REGISTRATION,
862 protocolHandlerRegistrationCallback);
863 evas_object_smart_callback_del(
865 EWK_PROTOCOLHANDLER_ISREGISTERED,
866 protocolHandlerIsRegisteredCallback);
867 evas_object_smart_callback_del(
869 EWK_PROTOCOLHANDLER_UNREGISTRATION,
870 protocolHandlerUnregistrationCallback);
872 evas_object_smart_callback_del(
874 EWK_CONTENTHANDLER_REGISTRATION,
875 contentHandlerRegistrationCallback);
876 evas_object_smart_callback_del(
878 EWK_CONTENTHANDLER_ISREGISTERED,
879 contentHandlerIsRegisteredCallback);
880 evas_object_smart_callback_del(
882 EWK_CONTENTHANDLER_UNREGISTRATION,
883 contentHandlerUnregistrationCallback);
886 void ViewLogic::createEwkView(Evas* canvas)
888 LogDebug("createEwkVeiw");
890 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
891 Evas_Object* newEwkView = ewk_view_add_with_context(
894 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
897 LogError("WKView creation failed");
902 // even arguments pass the ewkContext, this API should be called
903 // after webkit Evas_Object is created
904 Ewk_Cookie_Manager *ewkCookieManager;
906 ewk_context_cookie_manager_get(m_ewkContext);
907 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
908 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
910 LogInfo("push webview: " << newEwkView);
911 m_ewkViewList.push_back(newEwkView);
912 m_currentEwkView = newEwkView;
915 void ViewLogic::setStartPage()
917 /* Start URI (as other uris) is now localized
918 * on WebProcess side */
919 m_currentUri = m_startUrl;
922 void ViewLogic::prepareEwkView(Evas_Object *wkView)
924 LogDebug("prepareEwkView called");
926 Ewk_Settings* settings = ewk_view_settings_get(wkView);
929 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
930 if (customUserAgent.empty()) {
931 auto userAgentString =
932 ViewModule::UserAgentSupport::getUserAgentFromVconf();
933 if (!userAgentString.empty()) {
934 LogDebug("Setting user agent as: " << userAgentString);
935 ewk_view_user_agent_set(wkView, userAgentString.c_str());
938 LogDebug("Setting custom user agent as: " << customUserAgent);
939 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
942 // set custom header : language
943 using namespace ViewModule::CustomHeaderSupport;
944 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
945 if (!customHeaderString.empty()) {
946 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
947 LogDebug("custom value=[" << customHeaderString << "]");
948 ewk_view_custom_header_add(wkView,
949 ACCEPT_LANGUAGE.c_str(),
950 customHeaderString.c_str());
953 // webkit NPAPI plugins is always on in wrt
954 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
956 // The followings are not implemeted yet by webkit2
957 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
958 // ewk_view_mode_set();
959 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
960 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
961 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
962 // elm_webview_show_magnifier_set(EINA_FALSE);
963 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
964 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
965 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
967 // disable zoom option when user click the input field
968 // this option is useful with the normal website
969 // for the make user friendly, disable auto zoom in the webapp
970 // The followings are not implemeted yet by webkit2
971 // elm_webview_input_field_zoom_set(EINA_FALSE);
973 // set cookie database path
974 // The followings are not implemeted yet by webkit2
975 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
977 // set visibility to WebCore. This value will be used for html5.
978 // also, this value will be changed in the suspend, resume
979 // or create window, close window.
980 ewk_view_page_visibility_state_set(wkView,
981 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
985 void ViewLogic::removeEwkView(Evas_Object *wkView)
987 LogInfo("removeEwkView called");
989 Assert(0 != m_ewkViewList.size());
991 // unregister webview callbacks
992 ewkClientDeinit(wkView);
994 // suspend NPAPI plugin - Not implemented by Webkit2
995 // ewk_view_pause_or_resume_plugins();
996 evas_object_del(wkView);
997 m_ewkViewList.remove(wkView);
1000 void ViewLogic::resumeEwkView(Evas_Object *wkView)
1002 LogInfo("resumeEwkView called");
1005 // register webview callback
1006 ewkClientInit(wkView);
1009 resumeWebkit(wkView);
1014 void ViewLogic::suspendEwkView(Evas_Object *wkView)
1016 LogInfo("suspendEwkView called");
1020 suspendWebkit(wkView);
1022 // unregister webview callbacks
1023 ewkClientDeinit(wkView);
1028 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1030 LogDebug("resumeWebkit");
1033 // resume NPAPI plugin
1034 // The followings are not implemeted yet by webkit2
1035 // ewk_view_pause_or_resume_plugins(false);
1036 // ewk_view_pause_or_resume_video_audio(false);
1037 // ewk_view_javascript_resume();
1038 // ewk_view_enable_render();
1039 // ewk_view_reduce_plugins_frame_rate(false);
1040 ewk_view_resume(wkView);
1041 ewk_view_visibility_set(wkView, EINA_TRUE);
1042 ewk_view_page_visibility_state_set(wkView,
1043 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
1048 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1050 LogDebug("suspendWebkit");
1053 // suspend the followings
1054 // The followings are not implemeted yet by webkit2
1055 // ewk_view_pause_or_resume_plugins(true);
1056 // ewk_view_pause_or_resume_video_audio(true);
1058 // send visibility event to webpage
1059 ewk_view_page_visibility_state_set(wkView,
1060 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1062 ewk_view_suspend(wkView);
1063 ewk_view_visibility_set(wkView, EINA_FALSE);
1067 void ViewLogic::contextMessageFromInjectedBundleCallback(
1073 LogDebug("contextMessageFromInjectedBundleCallback called");
1075 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1076 // didRecieveMessageFromInjectedBundleCallback - returnData is null
1077 // didReceiveSynchronousMessageCallback - returnData isn't null
1078 // WKContextInjectedBundleClient bundleClient = {
1079 // kWKContextInjectedBundleClientCurrentVersion,
1080 // static_cast<void*>(this),
1081 // &didRecieveMessageFromInjectedBundleCallback,
1082 // &didReceiveSynchronousMessageCallback
1084 if (NULL == returnData) {
1085 This->didRecieveMessageFromInjectedBundle(name, body);
1087 This->didReceiveSynchronousMessage(name, body, returnData);
1091 void ViewLogic::didStartDownloadCallback(
1092 const char* downloadUrl,
1095 LogDebug("didStartDownloadCallback called");
1097 ViewLogic* This = static_cast<ViewLogic*>(data);
1098 Assert(downloadUrl);
1099 LogDebug("download url = " << downloadUrl);
1100 This->m_appsSupport->downloadRequest(
1106 void ViewLogic::loadStartedCallback(
1109 void* /*eventInfo*/)
1111 LogDebug("loadStartedCallback called");
1113 ViewLogic* This = static_cast<ViewLogic*>(data);
1114 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1116 // call loadFinish callback to wrt-client
1117 if (!This->m_cbs->loadStart.empty()) {
1118 This->m_cbs->loadStart(obj);
1123 void ViewLogic::loadFinishedCallback(
1126 void* /*eventInfo*/)
1128 LogDebug("loadFinishedCallback called");
1130 ViewLogic* This = static_cast<ViewLogic*>(data);
1133 const char* url = ewk_view_url_get(This->m_currentEwkView);
1134 if (NULL == url || strlen(url) == 0) {
1135 LogError("url is empty");
1137 DPL::OptionalString jsOptionalString =
1138 ViewModule::PasswordSupport::jsForAutoFillData(url);
1139 if (jsOptionalString.IsNull()) {
1140 LogError("Fail to get JS String");
1142 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1144 if(EINA_FALSE == ewk_view_script_execute(
1145 This->m_currentEwkView,
1147 didRunJavaScriptCallback,
1150 LogError("JS for auto fill data failed.");
1155 // call loadFinish callback to wrt-client
1156 if (!This->m_cbs->loadFinish.empty()) {
1157 This->m_cbs->loadFinish(obj);
1160 // set only encoded bundle
1161 double scale = elm_config_scale_get();
1162 PluginModuleSupport::setCustomProperties(
1165 ApplicationDataSingleton::Instance().getEncodedBundle());
1166 // check if 'appsevice' event is registed at the current frames.
1167 // If so, dispatch the event to frames.
1168 PluginModuleSupport::dispatchJavaScriptEvent(
1170 WrtPlugins::W3C::ServiceCustomEvent,
1173 // In this case, widget is reloaded in the background.
1174 // After finished load, bundle should disconnent callback.
1175 if (This->m_isBackgroundReload) {
1176 PluginModuleSupport::suspend(This->m_ewkContext);
1177 ewk_view_suspend(This->m_currentEwkView);
1178 This->m_isBackgroundReload = false;
1182 void ViewLogic::titleChangedCallback(
1184 Evas_Object* /*obj*/,
1187 LogDebug("titleChangedCallback called");
1189 ViewLogic* This = static_cast<ViewLogic*>(data);
1191 const char* title = static_cast<char*>(eventInfo);
1193 if (0 == strlen(title)) {
1194 LogDebug("title data is empty");
1197 LogDebug("Title = [" << title << "]");
1198 This->m_schemeSupport->HandleTizenScheme(title,
1200 This->m_currentEwkView);
1203 void ViewLogic::loadProgressCallback(
1205 Evas_Object* /*obj*/,
1208 double* progress = static_cast<double*>(eventInfo);
1209 LogDebug("didChangeProgressCallback progress = " << *progress);
1212 void ViewLogic::loadProgressFinishedCallback(
1214 Evas_Object* /*obj*/,
1215 void* /*eventInfo*/)
1217 LogDebug("didFinishProgressCallback");
1219 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1220 if (!view->m_cbs->progressFinish.empty()) {
1221 view->m_cbs->progressFinish();
1225 void ViewLogic::processCrashedCallback(
1227 Evas_Object* /*obj*/,
1230 LogInfo("processCrashedCallback");
1232 ViewLogic const * const view =
1233 static_cast<ViewLogic const * const>(data);
1234 if (!view->m_cbs->webCrash.empty()) {
1235 view->m_cbs->webCrash();
1237 // This flag will be prevented exit() call in the Webkit side
1238 if (NULL != eventInfo) {
1239 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1243 void ViewLogic::createWindowCallback(
1248 LogDebug("createWindowCallback");
1250 ViewLogic* This = static_cast<ViewLogic*>(data);
1252 // First, current webview should be handled by user callback
1253 if (!This->m_cbs->bufferUnset.empty()) {
1254 This->m_cbs->bufferUnset(obj);
1257 // this can be set by executable for specific purpose
1258 Evas* canvas = NULL;
1259 if (!This->m_cbs->windowCreateBefore.empty()) {
1260 // 'obj' is parent webview object
1261 This->m_cbs->windowCreateBefore(&canvas, obj);
1264 canvas = evas_object_evas_get(This->m_window);
1267 // create new ewkview
1268 This->createEwkView(canvas);
1269 Evas_Object* newEwkView = This->m_currentEwkView;
1271 // initialize new ewkview
1272 This->setStartPage();
1273 This->ewkClientInit(newEwkView);
1274 This->prepareEwkView(newEwkView);
1276 // Specific jobs of child, parent webview are handled by each executable
1277 if (!This->m_cbs->windowCreateAfter.empty()) {
1278 // 'obj' is parent webview, 'newEwkView' is child webview
1279 This->m_cbs->windowCreateAfter(obj, newEwkView);
1282 // Lastly, new webview should be handled by user callback
1283 if (!This->m_cbs->bufferSet.empty()) {
1284 This->m_cbs->bufferSet(newEwkView);
1286 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1289 void ViewLogic::closeWindowCallback(
1292 void* /*eventInfo*/)
1294 LogDebug("closeWindowCallback");
1295 ViewLogic* This = static_cast<ViewLogic*>(data);
1296 This->m_closedEwkView = obj;
1297 ecore_idler_add(windowCloseIdlerCallback, This);
1300 void ViewLogic::policyNavigationDecideCallback(
1302 Evas_Object* /*obj*/,
1305 LogDebug("policyNavigationDecideCallback called");
1307 ViewLogic* This = static_cast<ViewLogic*>(data);
1309 Ewk_Policy_Decision* policyDecision =
1310 static_cast<Ewk_Policy_Decision*>(eventInfo);
1312 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1316 This->m_currentEwkView))
1319 ewk_policy_decision_use(policyDecision);
1321 // check whether this is new empty window
1322 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1323 if(!activeUrl || 0 == strlen(activeUrl)) {
1325 * The view is empty and scheme has been handled externally. When
1326 * user gets back from the external application he'd see blank page
1327 * and won't be able to navigate back. This happens when window.open
1328 * is used to handle schemes like sms/mms/mailto (for example in
1329 * WAC web standards tests: WS-15XX).
1331 * To solve the problem, the empty view is removed from the stack
1332 * and the previous one is shown. This is not an elegant solution
1333 * but we don't have a better one.
1335 LogInfo("Scheme has been handled externally. Removing empty view.");
1336 if (ewk_view_back_possible(This->m_currentEwkView)) {
1337 // go back to previous WKPage
1338 ewk_view_back(This->m_currentEwkView);
1340 // stop current WKPage
1341 ewk_view_stop(This->m_currentEwkView);
1342 ecore_idler_add(windowCloseIdlerCallback, This);
1347 ewk_policy_decision_ignore(policyDecision);
1351 void ViewLogic::policyNewWindowDecideCallback(
1353 Evas_Object* /*obj*/,
1356 LogDebug("policyNewWindowDecideCallback called");
1358 ViewLogic* This = static_cast<ViewLogic*>(data);
1360 Ewk_Policy_Decision* policyDecision =
1361 static_cast<Ewk_Policy_Decision*>(eventInfo);
1363 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1367 This->m_currentEwkView))
1369 ewk_policy_decision_use(policyDecision);
1372 ewk_policy_decision_ignore(policyDecision);
1376 void ViewLogic::pageResponseDecideCallback(
1378 Evas_Object* /*obj*/,
1381 LogDebug("pageResponseDecideCallback called");
1383 ViewLogic* This = static_cast<ViewLogic*>(data);
1385 Ewk_Policy_Decision* policyDecision =
1386 static_cast<Ewk_Policy_Decision*>(eventInfo);
1387 Ewk_Policy_Decision_Type policyDecisionType =
1388 ewk_policy_decision_type_get(policyDecision);
1390 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1392 ewk_policy_decision_use(policyDecision);
1393 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1394 LogDebug("download");
1395 ewk_policy_decision_suspend(policyDecision);
1397 // get uri information
1398 const char* url = ewk_policy_decision_url_get(policyDecision);
1399 if (NULL == url || strlen(url) == 0) {
1400 LogDebug("url data is empty");
1401 ewk_policy_decision_use(policyDecision);
1404 LogDebug("url = [" << url << "]");
1406 // get content information
1407 const char* content =
1408 ewk_policy_decision_response_mime_get(policyDecision);
1409 LogDebug("content type = [" << content << "]");
1411 // get cookie information
1412 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1413 LogDebug("cookie = [" << cookie << "]");
1415 LogDebug("Content not supported, will be opened in external app");
1416 This->m_appsSupport->downloadRequest(
1420 ewk_policy_decision_ignore(policyDecision);
1421 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1423 ewk_policy_decision_ignore(policyDecision);
1425 LogDebug("Type isn't handled");
1426 ewk_policy_decision_ignore(policyDecision);
1430 void ViewLogic::contextmenuCustomizeCallback(
1432 Evas_Object* /*obj*/,
1435 LogDebug("contextmenuCustomizeCallback called");
1438 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1439 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1440 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1441 (This->m_model->SettingList.Get().getContextMenu()
1442 == ContextMenu_Disable))
1444 LogDebug("ContextMenu Disable!!");
1445 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1446 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1448 ewk_context_menu_item_remove(menu, item);
1451 LogDebug("ContextMenu Enable!!");
1452 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1453 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1455 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1458 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1459 ewk_context_menu_item_remove(menu, item);
1462 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1463 ewk_context_menu_item_remove(menu, item);
1474 void ViewLogic::formSubmitCallback(
1476 Evas_Object* /*obj*/,
1479 LogDebug("formSubmitCallback called");
1481 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1483 const char* uri = ewk_form_data_url_get(formData);
1485 LogError("URL is empty");
1489 Eina_Hash* userData = ewk_form_data_values_get(formData);
1490 ViewModule::PasswordSupport::submitClicked(uri, userData);
1493 void ViewLogic::geolocationPermissionRequestCallback(
1495 Evas_Object* /*obj*/,
1499 ViewLogic* This = static_cast<ViewLogic*>(data);
1501 Ewk_Geolocation_Permission_Data* permissionRequest =
1502 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1504 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1505 SecurityOriginDB::FEATURE_GEOLOCATION)
1506 == WrtDB::SETTINGS_TYPE_OFF)
1508 ewk_geolocation_permission_request_allow_set(
1509 ewk_geolocation_permission_request_get(permissionRequest),
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);
1577 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1578 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1579 == WrtDB::SETTINGS_TYPE_OFF)
1581 Ewk_Notification_Permission_Request* request =
1582 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1583 ewk_notification_permission_request_response(
1591 ViewModule::WebNotification::webNotificationPermissionRequest(
1593 This->m_securityOriginSupport->getSecurityOriginDAO(),
1599 void ViewLogic::vibrationVibrateCallback(
1601 Evas_Object* /*obj*/,
1604 LogDebug("vibrationVibrateCallback called");
1606 ViewLogic* This = static_cast<ViewLogic*>(data);
1609 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1612 // This->m_vibrationSupport->startVibration(vibrationTime);
1617 void ViewLogic::vibrationCancelCallback(
1619 Evas_Object* /*obj*/,
1620 void* /*eventInfo*/)
1622 LogDebug("vibrationCancelCallback called");
1624 ViewLogic* This = static_cast<ViewLogic*>(data);
1627 // This->m_vibrationSupport->stopVibration();
1632 // EWK Orientation Callback
1633 Eina_Bool ViewLogic::orientationLockCallback(
1635 Eina_Bool /*needLock*/,
1639 LogDebug("orientationLockCallback called");
1641 ViewLogic* This = static_cast<ViewLogic*>(data);
1643 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1644 LogDebug("orientation is portrait-primary");
1645 elm_win_rotation_with_resize_set(This->m_window, 0);
1646 ewk_view_orientation_send(obj, 0);
1647 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1648 LogDebug("orientation is landscape-primary");
1649 elm_win_rotation_with_resize_set(This->m_window, 270);
1650 ewk_view_orientation_send(obj, 90);
1651 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1652 LogDebug("orientation is portrait-secondary");
1653 elm_win_rotation_with_resize_set(This->m_window, 180);
1654 ewk_view_orientation_send(obj, 180);
1655 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1656 LogDebug("orientation is landscape-secondary");
1657 elm_win_rotation_with_resize_set(This->m_window, 90);
1658 ewk_view_orientation_send(obj, -90);
1660 LogDebug("Wrong orientation is set");
1667 // Fullscreen API callbacks
1668 void ViewLogic::enterFullscreenCallback(
1670 Evas_Object* /*obj*/,
1671 void* /*eventInfo*/)
1673 LogInfo("enterFullscreenCallback called");
1675 ViewLogic* This = static_cast<ViewLogic*>(data);
1676 if (!This->m_cbs->toggleFullscreen.empty()) {
1677 This->m_cbs->toggleFullscreen(true);
1680 void ViewLogic::exitFullscreenCallback(
1682 Evas_Object* /*obj*/,
1683 void* /*eventInfo*/)
1685 LogInfo("exitFullscreenCallback called");
1687 ViewLogic* This = static_cast<ViewLogic*>(data);
1688 if (!This->m_cbs->toggleFullscreen.empty()) {
1689 This->m_cbs->toggleFullscreen(false);
1693 void ViewLogic::imeChangedCallback(
1695 Evas_Object* /*obj*/,
1701 ViewLogic* This = static_cast<ViewLogic*>(data);
1702 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1703 This->m_imeWidth = rect->w;
1704 This->m_imeHeight = rect->h;
1707 void ViewLogic::imeOpenedCallback(
1709 Evas_Object* /*obj*/,
1710 void* /*eventInfo*/)
1714 ViewLogic* This = static_cast<ViewLogic*>(data);
1716 using namespace WrtPlugins::W3C;
1717 SoftKeyboardChangeArgs args;
1718 args.state = IME_STATE_ON;
1719 args.width = This->m_imeWidth;
1720 args.height = This->m_imeHeight;
1721 This->fireJavascriptEvent(
1722 static_cast<int>(SoftKeyboardChangeCustomEvent),
1726 void ViewLogic::imeClosedCallback(
1728 Evas_Object* /*obj*/,
1729 void* /*eventInfo*/)
1733 ViewLogic* This = static_cast<ViewLogic*>(data);
1735 using namespace WrtPlugins::W3C;
1736 SoftKeyboardChangeArgs args;
1737 args.state = IME_STATE_OFF;
1739 This->fireJavascriptEvent(
1740 static_cast<int>(SoftKeyboardChangeCustomEvent),
1744 void ViewLogic::usermediaPermissionRequestCallback(
1746 Evas_Object* /*obj*/,
1749 LogDebug("usermediaPermissionRequestCallback called");
1751 ViewLogic* This = static_cast<ViewLogic*>(data);
1752 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1758 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1761 Ewk_Custom_Handlers_Data* handler =
1762 static_cast<Ewk_Custom_Handlers_Data*>(data);
1763 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1764 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1766 LogDebug("base url: " << base_url);
1767 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1769 const char* url = ewk_custom_handlers_data_url_get(handler);
1771 LogDebug("url: " << url);
1772 customHandler->url = DPL::FromASCIIString(string(url));
1774 const char* target = ewk_custom_handlers_data_target_get(handler);
1776 LogDebug("target: " << target);
1777 customHandler->target = DPL::FromASCIIString(string(target));
1779 const char* title = ewk_custom_handlers_data_title_get(handler);
1781 LogDebug("title: " << title);
1782 customHandler->title = DPL::FromASCIIString(string(title));
1784 return customHandler;
1787 void ViewLogic::attachToCustomHandlersDao()
1789 if (!m_attachedToCustomHandlerDao) {
1790 CustomHandlerDB::Interface::attachDatabaseRW();
1794 void ViewLogic::detachFromCustomHandlersDao()
1796 if (m_attachedToCustomHandlerDao) {
1797 CustomHandlerDB::Interface::detachDatabase();
1801 const int protocolWhiteListLenth = 15;
1802 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1820 const int contentBlackListLenth = 14;
1821 char const * const contentBlackList[contentBlackListLenth] = {
1822 "application/x-www-form-urlencoded",
1823 "application/xhtml+xml",
1829 "multipart/x-mixed-replace",
1830 "text/cache-manifest",
1839 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1842 * @param customHandler
1844 void saveUserResponse(Wrt::Popup::PopupResponse response,
1845 CustomHandlerDB::CustomHandlerPtr customHandler)
1848 case Wrt::Popup::YES_DO_REMEMBER:
1849 LogDebug("User allowed, remember");
1850 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1851 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1853 case Wrt::Popup::YES_DONT_REMEMBER:
1854 LogDebug("User allowed, don't remember");
1855 customHandler->user_decision = CustomHandlerDB::Agreed;
1857 case Wrt::Popup::NO_DO_REMEMBER:
1858 LogDebug("User didn't allow, remember");
1859 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1860 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1862 case Wrt::Popup::NO_DONT_REMEMBER:
1863 LogDebug("User didn't allow, don't remember");
1864 customHandler->user_decision = CustomHandlerDB::Declined;
1869 //TODO registration, checking if registered and unregistration can be done in
1870 //common functions for both types of handlers. Only white and black lists
1871 //have to be separated
1872 //TODO attach database only one at the start (not in every callback?)
1873 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1879 CustomHandlerDB::CustomHandlerPtr customHandler =
1880 getCustomHandlerFromData(eventInfo);
1882 std::string scheme = DPL::ToUTF8String(customHandler->target);
1883 if (scheme.empty()) {
1884 LogError("No scheme provided");
1885 //TODO what about securityError?
1888 bool matched = false;
1889 //scheme on whiteList
1890 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1891 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1893 LogDebug("Match found, protocol can be handled");
1898 //starts with web+ and have at least 5 chars (lowercase ASCII)
1899 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1900 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1901 //throw SecurityException
1908 if (c < 'a' || c > 'z') {
1909 LogWarning("Wrong char inside scheme. "
1910 << "Only lowercase ASCII letters accepted");
1911 //throw SecurityException
1918 ViewLogic* This = static_cast<ViewLogic*>(data);
1919 LogDebug("Creating handlers dao");
1920 This->attachToCustomHandlersDao();
1921 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1922 CustomHandlerDB::CustomHandlerPtr handler =
1923 handlersDao.getProtocolHandler(customHandler->target,
1925 customHandler->base_url);
1926 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1927 LogDebug("Protocol already registered - nothing to do");
1929 LogDebug("Protocol handler not found");
1930 Wrt::Popup::PopupResponse response =
1931 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1932 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1933 PROTOCOL_HANDLER_ASK_TITLE,
1934 PROTOCOL_HANDLER_ASK_MSG,
1935 PROTOCOL_HANDLER_ASK_REMEMBER);
1936 saveUserResponse(response, customHandler);
1937 if (customHandler->user_decision == CustomHandlerDB::Declined)
1939 handlersDao.registerProtocolHandler(*(customHandler.get()));
1940 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1941 //TODO remove old default handler somehow from appsvc
1942 LogDebug("Registering appservice entry");
1943 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1945 DPL::ToUTF8String(customHandler->target).c_str(),
1946 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1947 if (APPSVC_RET_OK != ret)
1949 LogWarning("Appsvc entry failed: " << ret);
1952 LogDebug("Protocal saved");
1955 This->detachFromCustomHandlersDao();
1958 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1963 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1964 ViewLogic* This = static_cast<ViewLogic*>(data);
1965 LogDebug("Creating handlers dao");
1966 This->attachToCustomHandlersDao();
1967 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1968 CustomHandlerDB::CustomHandlerPtr handler =
1969 handlersDao.getProtocolHandler(customHandler->target,
1971 customHandler->base_url);
1973 if (handler->user_decision & CustomHandlerDB::Agreed)
1974 ewk_custom_handlers_data_result_set(
1975 static_cast<Ewk_Custom_Handlers_Data*>(data),
1976 EWK_CUSTOM_HANDLERS_REGISTERED);
1978 ewk_custom_handlers_data_result_set(
1979 static_cast<Ewk_Custom_Handlers_Data*>(data),
1980 EWK_CUSTOM_HANDLERS_DECLINED);
1982 ewk_custom_handlers_data_result_set(
1983 static_cast<Ewk_Custom_Handlers_Data*>(data),
1984 EWK_CUSTOM_HANDLERS_NEW);
1985 This->detachFromCustomHandlersDao();
1988 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1993 CustomHandlerDB::CustomHandlerPtr customHandler =
1994 getCustomHandlerFromData(eventInfo);
1995 ViewLogic* This = static_cast<ViewLogic*>(data);
1996 LogDebug("Creating handlers dao");
1997 This->attachToCustomHandlersDao();
1998 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1999 CustomHandlerDB::CustomHandlerPtr handlerCheck =
2000 handlersDao.getProtocolHandler(customHandler->target,
2002 customHandler->base_url);
2004 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2005 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2007 handlersDao.unregisterProtocolHandler(customHandler->target,
2009 customHandler->base_url);
2011 LogDebug("Nothing to unregister");
2013 This->detachFromCustomHandlersDao();
2016 void ViewLogic::contentHandlerRegistrationCallback(void* data,
2022 CustomHandlerDB::CustomHandlerPtr customHandler =
2023 getCustomHandlerFromData(eventInfo);
2025 std::string mimeType = DPL::ToUTF8String(customHandler->target);
2026 if (mimeType.empty()) {
2027 LogError("No mimeType provided.");
2030 for (int i = 0; i < contentBlackListLenth; ++i)
2032 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
2034 LogWarning("mimeType blacklisted");
2035 //throw SecurityException
2040 ViewLogic* This = static_cast<ViewLogic*>(data);
2041 LogDebug("Creating handlers dao");
2042 This->attachToCustomHandlersDao();
2043 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2044 CustomHandlerDB::CustomHandlerPtr handler =
2045 handlersDao.getContentHandler(customHandler->target,
2047 customHandler->base_url);
2048 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
2049 LogDebug("Protocol already registered - nothing to do");
2051 LogDebug("Protocol handler not found");
2052 Wrt::Popup::PopupResponse response =
2053 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
2054 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
2055 CONTENT_HANDLER_ASK_TITLE,
2056 CONTENT_HANDLER_ASK_MSG,
2057 CONTENT_HANDLER_AKS_REMEMBER);
2058 saveUserResponse(response, customHandler);
2059 if (customHandler->user_decision == CustomHandlerDB::Declined)
2061 handlersDao.registerContentHandler(*(customHandler.get()));
2062 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
2063 //TODO remove old default handler somehow from appsvc
2064 LogDebug("Registering appservice entry");
2065 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
2066 DPL::ToUTF8String(customHandler->target).c_str(),
2068 DPL::ToUTF8String(This->m_model->TizenId).c_str());
2069 if (APPSVC_RET_OK != ret)
2071 LogWarning("Appsvc entry failed: " << ret);
2074 LogDebug("Content saved");
2076 This->detachFromCustomHandlersDao();
2079 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
2084 CustomHandlerDB::CustomHandlerPtr customHandler =
2085 getCustomHandlerFromData(eventInfo);
2086 ViewLogic* This = static_cast<ViewLogic*>(data);
2087 LogDebug("Creating handlers dao");
2089 This->attachToCustomHandlersDao();
2090 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2091 CustomHandlerDB::CustomHandlerPtr handler =
2092 handlersDao.getContentHandler(customHandler->target,
2094 customHandler->base_url);
2096 if (handler->user_decision & CustomHandlerDB::Agreed)
2097 ewk_custom_handlers_data_result_set(
2098 static_cast<Ewk_Custom_Handlers_Data*>(data),
2099 EWK_CUSTOM_HANDLERS_REGISTERED);
2101 ewk_custom_handlers_data_result_set(
2102 static_cast<Ewk_Custom_Handlers_Data*>(data),
2103 EWK_CUSTOM_HANDLERS_DECLINED);
2105 ewk_custom_handlers_data_result_set(
2106 static_cast<Ewk_Custom_Handlers_Data*>(data),
2107 EWK_CUSTOM_HANDLERS_NEW);
2108 This->detachFromCustomHandlersDao();
2111 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
2116 CustomHandlerDB::CustomHandlerPtr customHandler =
2117 getCustomHandlerFromData(eventInfo);
2118 ViewLogic* This = static_cast<ViewLogic*>(data);
2119 LogDebug("Creating handlers dao");
2120 This->attachToCustomHandlersDao();
2121 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2122 CustomHandlerDB::CustomHandlerPtr handlerCheck =
2123 handlersDao.getContentHandler(customHandler->target,
2125 customHandler->base_url);
2127 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2128 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2130 handlersDao.unregisterContentHandler(customHandler->target,
2132 customHandler->base_url);
2134 LogDebug("Nothing to unregister");
2135 This->detachFromCustomHandlersDao();
2138 void ViewLogic::didRunJavaScriptCallback(
2139 Evas_Object* /*obj*/,
2143 LogInfo("didRunJavaScriptCallback called");
2144 LogInfo("result = " << result);
2147 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
2149 LogDebug("closeIdlerCallback");
2150 ViewLogic* This = static_cast<ViewLogic*>(data);
2151 This->windowClose();
2152 return ECORE_CALLBACK_CANCEL;
2155 int ViewLogic::appcoreLowMemoryCallback(void *data)
2157 LogInfo("appcoreLowMemoryCallback");
2159 ViewLogic* This = static_cast<ViewLogic*>(data);
2161 if (NULL == This->m_ewkContext) {
2162 LogInfo("ewk isn't initialize at this moment");
2164 // Crash may occur on specific situation
2165 // So use the followings after they become stable
2166 //ewk_context_cache_clear(This->m_ewkContext);
2167 //ewk_context_notify_low_memory(This->m_ewkContext);
2173 void ViewLogic::databaseUsagePermissionRequestCallback(
2175 Evas_Object* /*obj*/,
2178 LogDebug("databaseUsagePermissionRequestCallback called");
2180 ViewLogic* This = static_cast<ViewLogic*>(data);
2183 if (This->m_securityOriginSupport->isNeedPermissionCheck(
2184 SecurityOriginDB::FEATURE_WEB_DATABASE)
2185 == WrtDB::SETTINGS_TYPE_OFF)
2187 // default value is deny
2190 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
2192 This->m_securityOriginSupport->getSecurityOriginDAO(),
2197 void ViewLogic::fileSystemPermissionRequestCallback(
2199 Evas_Object* /*obj*/,
2202 LogDebug("fileSystemPermissionRequestCallback called");
2204 ViewLogic* This = static_cast<ViewLogic*>(data);
2206 if (This->m_securityOriginSupport->isNeedPermissionCheck(
2207 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
2208 == WrtDB::SETTINGS_TYPE_OFF)
2210 Ewk_Context_File_System_Permission* fileSystemPermission =
2211 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
2212 ewk_context_file_system_permission_allow_set(fileSystemPermission,
2218 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
2220 This->m_securityOriginSupport->getSecurityOriginDAO(),
2224 void ViewLogic::didRecieveMessageFromInjectedBundle(
2226 const char* /*body*/)
2228 LogDebug("did recive message " << name);
2231 void ViewLogic::didReceiveSynchronousMessage(
2236 LogDebug("didReceiveSynchronousMessage called");
2241 LogDebug("body is empty");
2245 if (!strcmp(name, uriBlockedMessageName)) {
2246 LogDebug("received : " << uriBlockedMessageName);
2247 // Currently WebProcess informs obly about blocked
2248 // URI - URI localization and security chekcs are
2249 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2250 // and bundle_uri_handling.cpp)
2251 rememberBlockedURI(DPL::FromUTF8String(body));
2253 } else if (!strcmp(name, uriChangedMessageName)) {
2254 LogDebug("received : " << uriChangedMessageName);
2255 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2256 *returnData = strdup(ret.c_str());
2260 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2262 m_blockedUri = DPL::ToUTF8String(inputURI);
2263 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2267 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2269 using namespace ViewModule::SecuritySupport;
2271 std::string url = DPL::ToUTF8String(changedURL);
2272 LogInfo("URL = [" << url << "]");
2275 // If url is same to URICHANGE_BLOCKED_URL,
2276 // this url has been already blocked by willsend.
2277 // So current page should be moved to previous page
2278 if (url == URICHANGE_BLOCKED_URL)
2280 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2282 // block this page and open it in browser
2283 LogDebug("Request was blocked by WARP: " << url.c_str());
2284 if (!m_blockedUri.empty()) {
2285 LogDebug("open browser : " << m_blockedUri);
2286 bundle* bundleData = bundle_create();
2287 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2288 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2289 CONTROLLER_POST_EVENT(
2290 ApplicationLauncher,
2291 ApplicationLauncherEvents::LaunchApplicationByAppService(
2295 m_blockedUri = std::string();
2298 if (ewk_view_back_possible(m_currentEwkView)) {
2299 // go back to previous page
2300 ewk_view_back(m_currentEwkView);
2302 // stop current page
2303 ewk_view_stop(m_currentEwkView);
2304 ecore_idler_add(windowCloseIdlerCallback, this);
2307 // This is used in case of returning previous page
2309 return URICHANGE_PLUGIN_NO_CHANGE;
2314 // Check if this url with 'http' or 'https' is included in whitelist,
2315 // which has lists of accessible external documents and
2316 // used for ONLY Tizen app
2317 std::string matchedScheme;
2318 std::string matchedUri;
2319 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2322 ViewModule::Scheme scheme(matchedScheme);
2323 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2324 scheme.GetType() == ViewModule::Scheme::HTTPS)
2326 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2327 if (!checkWhitelist(url.c_str())) {
2328 LogInfo("This uri is not included in white document list");
2329 return URICHANGE_PLUGIN_STOP_ONLY;
2331 LogInfo("This url is included in WhiteList");
2333 // For WAC app, WRT should block access of device api
2334 // for external documents
2335 return URICHANGE_PLUGIN_STOP_ONLY;
2339 // register javascript object for plugins to be used
2340 LogInfo("Register Plugin Objects");
2341 return URICHANGE_PLUGIN_RESTART;
2344 void ViewLogic::windowClose()
2346 LogDebug("windowClose");
2347 Assert(m_closedEwkView && "no closed webview");
2349 if (1 >= m_ewkViewList.size()) {
2350 if (!m_cbs->webkitExit.empty()) {
2351 m_cbs->webkitExit();
2354 // call user callbacks
2355 if (!m_cbs->bufferUnset.empty()) {
2356 m_cbs->bufferUnset(m_currentEwkView);
2358 if (!m_cbs->windowClose.empty()) {
2359 m_cbs->windowClose(m_closedEwkView);
2361 removeEwkView(m_closedEwkView);
2363 // get latest ewkView
2364 m_currentEwkView = m_ewkViewList.back();
2365 const char* uri = ewk_view_url_get(m_currentEwkView);
2366 if (NULL == uri || 0 == strlen(uri)) {
2367 m_currentUri.clear();
2373 /* In case we support many pages in parallel
2374 then view is not suspended*/
2375 //resumeEwkView(m_currentEwkView);
2378 if (!m_cbs->bufferSet.empty()) {
2379 m_cbs->bufferSet(m_currentEwkView);