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>
31 #include <dpl/foreach.h>
33 #include <appcore-common.h>
37 #include <widget_model.h>
38 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
39 #include <dpl/wrt-dao-ro/vconf_config.h>
40 #include <dpl/utils/wrt_global_settings.h>
42 #include <common/application_data.h>
43 #include <common/application_launcher.h>
44 #include <common/scheme.h>
46 #include <common/view_logic_apps_support.h>
47 #include <common/view_logic_custom_header_support.h>
48 #include <common/view_logic_password_support.h>
49 #include <common/view_logic_security_support.h>
50 #include <common/view_logic_security_origin_support.h>
51 #include <common/view_logic_storage_support.h>
52 #include <common/view_logic_uri_support.h>
53 #include <common/view_logic_user_agent_support.h>
54 #include <common/view_logic_vibration_support.h>
55 #include <view_logic_scheme_support.h>
56 #include <view_logic_filesystem_support.h>
57 #include <view_logic_geolocation_support_webkit2.h>
58 #include <view_logic_usermedia_support.h>
59 #include <view_logic_web_notification_support.h>
60 #include <view_logic_web_storage_support.h>
61 #include "bundles/plugin_module_support.h"
62 #include <popup-runner/PopupInvoker.h>
65 #include <js_overlay_types.h>
66 #include <i_runnable_widget_object.h>
67 #include <profiling_util.h>
68 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
69 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
70 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
71 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
72 #include <popup-runner/PopupInvoker.h>
74 #include <appsvc/appsvc.h>
77 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
78 const char * const uriBlockedMessageName = "uri_block_msg";
79 const char * const uriChangedMessageName = "uri_changed_msg";
80 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
81 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
82 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
83 const char * const URICHANGE_BLOCKED_URL = "null";
84 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
85 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
87 const char * const IME_STATE_ON = "on";
88 const char * const IME_STATE_OFF = "off";
90 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
91 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
92 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
93 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
94 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
95 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
96 const char * const CERTIFICATE_CONFIRM_REQUEST_ASK_TITLE =
98 const char * const CERTIFICATE_CONFIRM_REQUEST_ASK_BODY =
99 "This site's security certificate is not trusted! Do you acess this site?";
101 const wchar_t* BACKGROUND_ENABLED = L"background_enabled";
102 } // anonymous namespace
104 std::map<const std::string,
105 const Evas_Smart_Cb> ViewLogic::m_ewkCallbacksMap = {
106 { "load,started", &ViewLogic::loadStartedCallback },
107 { "load,finished", &ViewLogic::loadFinishedCallback },
108 { "title,changed", &ViewLogic::titleChangedCallback },
109 { "load,progress", &ViewLogic::loadProgressCallback },
110 { "load,progress,finished", &ViewLogic::loadProgressFinishedCallback },
111 { "process,crashed", &ViewLogic::processCrashedCallback },
113 { "create,window", &ViewLogic::createWindowCallback },
114 { "close,window", &ViewLogic::closeWindowCallback },
115 // WKPagePolicyClient
116 { "policy,navigation,decide", &ViewLogic::policyNavigationDecideCallback },
117 { "policy,newwindow,decide", &ViewLogic::policyNewWindowDecideCallback },
118 { "policy,response,decide", &ViewLogic::pageResponseDecideCallback },
119 // WKPageContextMenuClient
120 { "contextmenu,customize", &ViewLogic::contextmenuCustomizeCallback },
122 { "form,submit", &ViewLogic::formSubmitCallback },
123 // EWK Geolocation Callback
124 { "request,geolocation,permission",
125 &ViewLogic::geolocationPermissionRequestCallback },
126 // EWK Notification Callback
127 { "notification,show", &ViewLogic::notificationShowCallback },
128 { "notification,cancel", &ViewLogic::notificationCancelCallback },
129 { "notification,permission,request",
130 &ViewLogic::notificationPermissionRequestCallback },
132 { "database,quota,exceeded",
133 &ViewLogic::databaseUsagePermissionRequestCallback },
134 { "filesystem,permission,request",
135 &ViewLogic::fileSystemPermissionRequestCallback },
136 { "fullscreen,enterfullscreen", &ViewLogic::enterFullscreenCallback },
137 { "fullscreen,exitfullscreen", &ViewLogic::exitFullscreenCallback },
139 // when ime start to be showed on the webview,
140 // this callback will be called
141 { "inputmethod,changed", &ViewLogic::imeChangedCallback },
142 // this callback will be called
143 // when ime finishes to be showed on the webview
144 // "event_info" arg of this callback is always NULL point
145 // if web content should know size of ime,
146 // use "inputmethod,changed" instead of this.
148 { "editorclient,ime,opened", &ViewLogic::imeOpenedCallback },
149 // when ime finished to be hidden,
150 // this callback will be called
151 { "editorclient,ime,closed", &ViewLogic::imeClosedCallback },
152 // EWK Usermedia Callback
153 { "usermedia,permission,request",
154 &ViewLogic::usermediaPermissionRequestCallback },
156 { "protocolhandler,registration,requested",
157 &ViewLogic::protocolHandlerRegistrationCallback },
158 { "protocolhandler,isregistered",
159 &ViewLogic::protocolHandlerIsRegisteredCallback },
160 { "protocolhandler,unregistration,requested",
161 &ViewLogic::protocolHandlerUnregistrationCallback },
162 { "contenthandler,registration,requested",
163 &ViewLogic::contentHandlerRegistrationCallback },
164 { "contenthandler,isregistered",
165 &ViewLogic::contentHandlerIsRegisteredCallback },
166 { "contenthandler,unregistration,requested",
167 &ViewLogic::contentHandlerUnregistrationCallback },
168 { "request,certificate,confirm",
169 &ViewLogic::certificateConfirmRequestCallback }
172 ViewLogic::ViewLogic() :
177 m_cbs(new WRT::UserDelegates),
178 m_isBackgroundReload(false),
179 m_isBackgroundSupport(false),
180 m_appsSupport(new ViewModule::AppsSupport()),
181 m_vibrationSupport(new ViewModule::VibrationSupport()),
182 m_attachedToCustomHandlerDao(false)
185 ViewLogic::~ViewLogic()
187 detachFromCustomHandlersDao();
190 bool ViewLogic::createWebView(Ewk_Context* context,
194 initializeEwkContext(context);
195 Assert(NULL != m_ewkContext);
198 if (!createEwkView(evas_object_evas_get(m_window))) {
204 void ViewLogic::destroyWebView()
207 finalizeEwkContext();
211 void ViewLogic::initialize()
213 LogDebug("Initializing");
214 ApplicationLauncherSingleton::Instance().Touch();
215 appcore_set_event_callback(
216 APPCORE_EVENT_LOW_MEMORY,
217 &appcoreLowMemoryCallback,
221 void ViewLogic::terminate()
223 LogDebug("terminating view logic");
227 LogError("Widget model not created");
232 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
234 LogDebug("View prepare");
238 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
239 Assert(NULL != m_ewkContext);
242 ADD_PROFILING_POINT("initializeSupport", "start");
244 ADD_PROFILING_POINT("initializeSupport", "stop");
246 ewkClientInit(m_currentEwkView);
247 ADD_PROFILING_POINT("prepareEwkView", "start");
248 prepareEwkView(m_currentEwkView);
249 ADD_PROFILING_POINT("prepareEwkView", "stop");
250 initializePluginLoading();
253 void ViewLogic::showWidget()
255 LogDebug("showing widget");
256 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
257 if (m_currentUri.empty()) {
258 LogError("Localized current URI doesn't exist");
262 LogInfo("m_currentUri: " << m_currentUri);
265 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
267 if (!m_cbs->bufferSet.empty()) {
268 m_cbs->bufferSet(m_currentEwkView);
272 void ViewLogic::hideWidget()
274 LogDebug("hiding widget");
275 ViewModule::StorageSupport::deinitializeStorage(m_model);
276 m_appsSupport->deinitialize();
278 m_vibrationSupport->deinitialize();
280 while (m_ewkViewList.size()) {
281 LogInfo("pop webview: " << m_ewkViewList.back());
282 removeEwkView(m_ewkViewList.back());
284 m_ewkViewList.clear();
287 void ViewLogic::suspendWidget()
289 LogInfo("Pausing widget");
292 LogDebug("Request bundle to suspend");
293 PluginModuleSupport::suspend(m_ewkContext);
295 if (!m_currentEwkView) {
296 LogWarning("Cannot suspend widget without view");
298 setEwkViewInvisible(m_currentEwkView);
299 if (!m_isBackgroundSupport) {
300 suspendWebkit(m_currentEwkView);
304 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
306 // call user callback
307 if (!m_cbs->suspend.empty()) {
308 m_cbs->suspend(true);
312 void ViewLogic::resumeWidget()
314 LogInfo("Resume widget");
317 LogDebug("Request bundle to resume");
318 PluginModuleSupport::resume(m_ewkContext);
320 if (m_currentEwkView) {
321 setEwkViewVisible(m_currentEwkView);
322 if (!m_isBackgroundSupport) {
323 resumeWebkit(m_currentEwkView);
327 /* window system team recomend removing this win_raise code. */
330 * elm_win_raise(m_window);
333 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
335 // call user callback
336 if (!m_cbs->resume.empty()) {
341 void ViewLogic::resetWidget()
343 LogInfo("Resetting Widget");
345 // destory all webview
346 while (m_ewkViewList.size()) {
347 LogInfo("pop webview: " << m_ewkViewList.back());
348 removeEwkView(m_ewkViewList.back());
350 m_ewkViewList.clear();
352 // create new webview
353 createEwkView(evas_object_evas_get(m_window));
355 ewkClientInit(m_currentEwkView);
356 prepareEwkView(m_currentEwkView);
358 // check if current url is service url for this tizen service
359 std::string requestedUri =
360 ViewModule::UriSupport::getUri(m_model, m_startUrl);
361 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
362 DPL::FromUTF8String(requestedUri.c_str()),
365 initializePluginLoading();
368 PluginModuleSupport::resume(m_ewkContext);
369 m_currentUri = DPL::ToUTF8String(*servicedUri);
370 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
371 elm_win_activate(m_window);
372 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
374 // call user callback
375 if (!m_cbs->reset.empty()) {
378 if (!m_cbs->bufferSet.empty()) {
379 m_cbs->bufferSet(m_currentEwkView);
383 void ViewLogic::backward()
385 if (ewk_view_back_possible(m_currentEwkView)) {
386 ewk_view_back(m_currentEwkView);
388 if (1 >= m_ewkViewList.size()) {
389 // If there is no previous page, widget move to backgroud.
390 LogInfo("Widget move to backgroud");
391 elm_win_lower(m_window);
393 // Back to previous webview
394 LogInfo("Widget move to previous webview");
395 m_closedEwkView = m_currentEwkView;
396 ecore_idler_add(windowCloseIdlerCallback, this);
401 void ViewLogic::reloadStartPage()
403 LogInfo("Reload Start Page");
404 // prevent fail to load plugin bundle side
405 m_isBackgroundReload = true;
406 PluginModuleSupport::resume(m_ewkContext);
408 if (m_ewkViewList.size() != 0) {
409 while (m_ewkViewList.size() > 0) {
410 if (!m_cbs->bufferUnset.empty()) {
411 m_cbs->bufferUnset(m_currentEwkView);
413 removeEwkView(m_currentEwkView);
417 // create new webview
418 createEwkView(evas_object_evas_get(m_window));
419 ewkClientInit(m_currentEwkView);
422 prepareEwkView(m_currentEwkView);
423 initializePluginLoading();
426 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
429 if (!m_cbs->bufferSet.empty()) {
430 m_cbs->bufferSet(m_currentEwkView);
432 LogInfo("Reloading Start Page is done!");
435 Evas_Object* ViewLogic::getCurrentWebview()
437 LogInfo("get current webview");
438 return m_currentEwkView;
441 void ViewLogic::fireJavascriptEvent(int event, void* data)
443 PluginModuleSupport::dispatchJavaScriptEvent(
445 static_cast<WrtPlugins::W3C::CustomEventType>(event),
449 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
454 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
456 LogInfo("initializeEwkContext called");
457 Assert(newEwkContext && "Ewk_Context provided can not be null");
458 // bundle callback setting
459 ewk_context_message_from_injected_bundle_callback_set(
461 contextMessageFromInjectedBundleCallback,
462 static_cast<void*>(this));
464 // proxy server setting
465 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
466 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
467 || (strstr(proxyAddress, "0.0.0.0")))
469 LogInfo("proxy address is empty");
470 ewk_context_proxy_uri_set(newEwkContext, NULL);
472 LogInfo("proxy address [" << proxyAddress << "]");
473 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
482 const char *theme = elm_theme_get(NULL);
485 LogInfo("theme is " << m_theme);
488 // Ewk download callback (WKContextDownloadClient)
489 ewk_context_did_start_download_callback_set(
491 didStartDownloadCallback,
494 ewk_context_vibration_client_callbacks_set(
496 vibrationVibrateCallback,
497 vibrationCancelCallback,
500 ewk_context_certificate_file_set(m_ewkContext,
501 "/opt/usr/share/certs/ca-certificate.crt");
503 // set to member value
504 m_ewkContext = newEwkContext;
507 void ViewLogic::finalizeEwkContext()
509 LogInfo("finalizeEwkContext called");
510 ewk_context_message_from_injected_bundle_callback_set(
514 ewk_context_did_start_download_callback_set(
518 ewk_context_vibration_client_callbacks_set(
523 // ewk_context_delete(m_ewkContext);
527 void ViewLogic::initializeSupport()
529 // background support
530 if (m_model->SettingList.Get().getBackgroundSupport()
531 == BackgroundSupport_Enable)
533 LogDebug("Background support enabled, set process active");
534 pid_t pid = getpid();
535 sysman_inform_active(pid);
536 m_isBackgroundSupport = true;
538 #ifndef DEPRECATED_SETTING_STRING
540 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
541 WrtDB::PropertyDAOReadOnly::WidgetPropertyValue bgEnableValue =
542 dao.getPropertyValue(DPL::String(BACKGROUND_ENABLED));
544 if (!bgEnableValue.IsNull() && !bgEnableValue->compare(L"true")) {
546 LogDebug("Background support enabled, set process active");
547 pid_t pid = getpid();
548 sysman_inform_active(pid);
549 m_isBackgroundSupport = true;
554 // set local stroage database path
555 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
556 ewk_context_web_storage_path_set(m_ewkContext,
557 dao.getPrivateLocalStoragePath().c_str());
558 // memory saving mode
561 WrtDB::VconfConfig::GetVconfKeyMemorySavingMode(
562 m_model->TizenId).c_str(),
564 ewk_context_memory_saving_mode_set(
566 static_cast<WrtDB::SettingsType>(result) ==
567 WrtDB::SETTINGS_TYPE_ON ? EINA_TRUE : EINA_FALSE);
568 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
569 ViewModule::StorageSupport::initializeStorage(m_model);
570 m_appsSupport->initialize(m_model);
571 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
573 m_vibrationSupport->initialize();
576 void ViewLogic::initializePluginLoading()
578 // inform wrt information for plugin loading to web process
579 PluginModuleSupport::start(
582 elm_config_scale_get(),
583 ApplicationDataSingleton::Instance().getEncodedBundle(),
585 m_model->SettingList.Get().isEncrypted());
588 void ViewLogic::ewkClientInit(Evas_Object *wkView)
590 Assert(NULL != wkView && "ewk_view not created at this point");
592 FOREACH(it, m_ewkCallbacksMap) {
593 evas_object_smart_callback_add(
599 // EWK Orientation Callback
600 ewk_view_orientation_lock_callback_set(
602 orientationLockCallback,
606 void ViewLogic::ewkClientDeinit(Evas_Object *wkView)
608 LogDebug("ewkClientDeinit");
609 Assert(NULL != wkView && "ewk_view not created at this point");
611 FOREACH(it, m_ewkCallbacksMap) {
612 evas_object_smart_callback_del(
617 ewk_view_orientation_lock_callback_set(
623 bool ViewLogic::createEwkView(Evas* canvas)
625 LogDebug("createEwkVeiw");
627 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
628 Evas_Object* newEwkView = ewk_view_add_with_context(
631 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
634 LogError("View creation failed");
635 Wrt::Popup::PopupInvoker().showInfo(
636 "Info", "View creation failed", "close");
641 // even arguments pass the ewkContext, this API should be called
642 // after webkit Evas_Object is created
643 Ewk_Cookie_Manager *ewkCookieManager;
645 ewk_context_cookie_manager_get(m_ewkContext);
646 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
647 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
649 LogInfo("push webview: " << newEwkView);
650 m_ewkViewList.push_back(newEwkView);
651 m_currentEwkView = newEwkView;
655 void ViewLogic::setStartPage()
657 /* Start URI (as other uris) is now localized
658 * on WebProcess side */
659 m_currentUri = m_startUrl;
662 void ViewLogic::prepareEwkView(Evas_Object *wkView)
664 LogDebug("prepareEwkView called");
666 Ewk_Settings* settings = ewk_view_settings_get(wkView);
669 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
670 if (customUserAgent.empty()) {
671 auto userAgentString =
672 ViewModule::UserAgentSupport::getUserAgentFromVconf();
673 if (!userAgentString.empty()) {
674 LogDebug("Setting user agent as: " << userAgentString);
675 ewk_view_user_agent_set(wkView, userAgentString.c_str());
678 LogDebug("Setting custom user agent as: " << customUserAgent);
679 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
682 // set custom header : language
683 using namespace ViewModule::CustomHeaderSupport;
684 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
685 if (!customHeaderString.empty()) {
686 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
687 LogDebug("custom value=[" << customHeaderString << "]");
688 ewk_view_custom_header_add(wkView,
689 ACCEPT_LANGUAGE.c_str(),
690 customHeaderString.c_str());
693 // webkit NPAPI plugins is always on in wrt
694 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
696 // The followings are not implemeted yet by webkit2
697 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
698 // ewk_view_mode_set();
699 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE,
701 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
702 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
703 // elm_webview_show_magnifier_set(EINA_FALSE);
704 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
705 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
706 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
708 // disable zoom option when user click the input field
709 // this option is useful with the normal website
710 // for the make user friendly, disable auto zoom in the webapp
711 // The followings are not implemeted yet by webkit2
712 // elm_webview_input_field_zoom_set(EINA_FALSE);
714 // set cookie database path
715 // The followings are not implemeted yet by webkit2
716 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
718 // set visibility to WebCore. This value will be used for html5.
719 // also, this value will be changed in the suspend, resume
720 // or create window, close window.
721 ewk_view_page_visibility_state_set(wkView,
722 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
726 void ViewLogic::removeEwkView(Evas_Object *wkView)
728 LogInfo("removeEwkView called");
730 Assert(0 != m_ewkViewList.size());
732 // unregister webview callbacks
733 ewkClientDeinit(wkView);
735 // suspend NPAPI plugin - Not implemented by Webkit2
736 // ewk_view_pause_or_resume_plugins();
737 evas_object_del(wkView);
738 m_ewkViewList.remove(wkView);
741 void ViewLogic::resumeEwkView(Evas_Object *wkView)
743 LogInfo("resumeEwkView called");
746 // register webview callback
747 ewkClientInit(wkView);
750 resumeWebkit(wkView);
755 void ViewLogic::suspendEwkView(Evas_Object *wkView)
757 LogInfo("suspendEwkView called");
761 suspendWebkit(wkView);
763 // unregister webview callbacks
764 ewkClientDeinit(wkView);
769 void ViewLogic::setEwkViewInvisible(Evas_Object *wkView)
771 LogInfo("setEwkViewInvisible called");
774 ewk_view_page_visibility_state_set(wkView,
775 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
777 ewk_view_visibility_set(wkView, EINA_FALSE);
780 void ViewLogic::setEwkViewVisible(Evas_Object *wkView)
782 LogInfo("setEwkViewVisible called");
785 ewk_view_page_visibility_state_set(wkView,
786 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
788 ewk_view_visibility_set(wkView, EINA_TRUE);
791 void ViewLogic::resumeWebkit(Evas_Object *wkView)
793 LogDebug("resumeWebkit");
796 // resume NPAPI plugin
797 // The followings are not implemeted yet by webkit2
798 // ewk_view_pause_or_resume_plugins(false);
799 // ewk_view_pause_or_resume_video_audio(false);
800 // ewk_view_javascript_resume();
801 // ewk_view_enable_render();
802 // ewk_view_reduce_plugins_frame_rate(false);
803 ewk_view_resume(wkView);
808 void ViewLogic::suspendWebkit(Evas_Object *wkView)
810 LogDebug("suspendWebkit");
813 // suspend the followings
814 // The followings are not implemeted yet by webkit2
815 // ewk_view_pause_or_resume_plugins(true);
816 // ewk_view_pause_or_resume_video_audio(true);
817 ewk_view_suspend(wkView);
822 void ViewLogic::contextMessageFromInjectedBundleCallback(
828 LogDebug("contextMessageFromInjectedBundleCallback called");
830 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
831 // didRecieveMessageFromInjectedBundleCallback - returnData is null
832 // didReceiveSynchronousMessageCallback - returnData isn't null
833 // WKContextInjectedBundleClient bundleClient = {
834 // kWKContextInjectedBundleClientCurrentVersion,
835 // static_cast<void*>(this),
836 // &didRecieveMessageFromInjectedBundleCallback,
837 // &didReceiveSynchronousMessageCallback
839 if (NULL == returnData) {
840 This->didRecieveMessageFromInjectedBundle(name, body);
842 This->didReceiveSynchronousMessage(name, body, returnData);
846 void ViewLogic::didStartDownloadCallback(
847 const char* downloadUrl,
850 LogDebug("didStartDownloadCallback called");
852 ViewLogic* This = static_cast<ViewLogic*>(data);
854 LogDebug("download url = " << downloadUrl);
855 This->m_appsSupport->downloadRequest(
861 void ViewLogic::loadStartedCallback(
866 LogDebug("loadStartedCallback called");
868 ViewLogic* This = static_cast<ViewLogic*>(data);
869 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
871 // call loadFinish callback to wrt-client
872 if (!This->m_cbs->loadStart.empty()) {
873 This->m_cbs->loadStart(obj);
877 void ViewLogic::loadFinishedCallback(
882 LogDebug("loadFinishedCallback called");
884 ViewLogic* This = static_cast<ViewLogic*>(data);
887 const char* url = ewk_view_url_get(This->m_currentEwkView);
888 if (NULL == url || strlen(url) == 0) {
889 LogError("url is empty");
891 DPL::OptionalString jsOptionalString =
892 ViewModule::PasswordSupport::jsForAutoFillData(url);
893 if (jsOptionalString.IsNull()) {
894 LogError("Fail to get JS String");
896 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
898 if (EINA_FALSE == ewk_view_script_execute(
899 This->m_currentEwkView,
901 didRunJavaScriptCallback,
904 LogError("JS for auto fill data failed.");
909 // call loadFinish callback to wrt-client
910 if (!This->m_cbs->loadFinish.empty()) {
911 This->m_cbs->loadFinish(obj);
914 // set only encoded bundle
915 double scale = elm_config_scale_get();
916 PluginModuleSupport::setCustomProperties(
919 ApplicationDataSingleton::Instance().getEncodedBundle());
920 // check if 'appsevice' event is registed at the current frames.
921 // If so, dispatch the event to frames.
922 PluginModuleSupport::dispatchJavaScriptEvent(
924 WrtPlugins::W3C::ServiceCustomEvent,
927 // In this case, widget is reloaded in the background.
928 // After finished load, bundle should disconnent callback.
929 if (This->m_isBackgroundReload) {
930 PluginModuleSupport::suspend(This->m_ewkContext);
931 ewk_view_suspend(This->m_currentEwkView);
932 This->m_isBackgroundReload = false;
936 void ViewLogic::titleChangedCallback(
938 Evas_Object* /*obj*/,
941 LogDebug("titleChangedCallback called");
943 ViewLogic* This = static_cast<ViewLogic*>(data);
945 const char* title = static_cast<char*>(eventInfo);
947 if (0 == strlen(title)) {
948 LogDebug("title data is empty");
951 LogDebug("Title = [" << title << "]");
952 This->m_schemeSupport->HandleTizenScheme(title,
954 This->m_currentEwkView);
957 void ViewLogic::loadProgressCallback(
959 Evas_Object* /*obj*/,
962 double* progress = static_cast<double*>(eventInfo);
963 LogDebug("didChangeProgressCallback progress = " << *progress);
966 void ViewLogic::loadProgressFinishedCallback(
968 Evas_Object* /*obj*/,
971 LogDebug("didFinishProgressCallback");
973 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
974 if (!view->m_cbs->progressFinish.empty()) {
975 view->m_cbs->progressFinish();
979 void ViewLogic::processCrashedCallback(
981 Evas_Object* /*obj*/,
984 LogInfo("processCrashedCallback");
986 ViewLogic const * const view =
987 static_cast<ViewLogic const * const>(data);
988 if (!view->m_cbs->webCrash.empty()) {
989 view->m_cbs->webCrash();
991 // This flag will be prevented exit() call in the Webkit side
992 if (NULL != eventInfo) {
993 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
997 void ViewLogic::createWindowCallback(
1002 LogDebug("createWindowCallback");
1004 ViewLogic* This = static_cast<ViewLogic*>(data);
1006 // First, current webview should be handled by user callback
1007 if (!This->m_cbs->bufferUnset.empty()) {
1008 This->m_cbs->bufferUnset(obj);
1011 // this can be set by executable for specific purpose
1012 Evas* canvas = NULL;
1013 if (!This->m_cbs->windowCreateBefore.empty()) {
1014 // 'obj' is parent webview object
1015 This->m_cbs->windowCreateBefore(&canvas, obj);
1018 canvas = evas_object_evas_get(This->m_window);
1021 // create new ewkview
1022 This->createEwkView(canvas);
1023 Evas_Object* newEwkView = This->m_currentEwkView;
1025 // initialize new ewkview
1026 This->setStartPage();
1027 This->ewkClientInit(newEwkView);
1028 This->prepareEwkView(newEwkView);
1030 // Specific jobs of child, parent webview are handled by each executable
1031 if (!This->m_cbs->windowCreateAfter.empty()) {
1032 // 'obj' is parent webview, 'newEwkView' is child webview
1033 This->m_cbs->windowCreateAfter(obj, newEwkView);
1036 // Lastly, new webview should be handled by user callback
1037 if (!This->m_cbs->bufferSet.empty()) {
1038 This->m_cbs->bufferSet(newEwkView);
1040 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1043 void ViewLogic::closeWindowCallback(
1046 void* /*eventInfo*/)
1048 LogDebug("closeWindowCallback");
1049 ViewLogic* This = static_cast<ViewLogic*>(data);
1050 This->m_closedEwkView = obj;
1051 ecore_idler_add(windowCloseIdlerCallback, This);
1054 void ViewLogic::policyNavigationDecideCallback(
1056 Evas_Object* /*obj*/,
1059 LogDebug("policyNavigationDecideCallback called");
1061 ViewLogic* This = static_cast<ViewLogic*>(data);
1063 Ewk_Policy_Decision* policyDecision =
1064 static_cast<Ewk_Policy_Decision*>(eventInfo);
1066 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1070 This->m_currentEwkView))
1073 ewk_policy_decision_use(policyDecision);
1075 // check whether this is new empty window
1076 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1077 if (!activeUrl || 0 == strlen(activeUrl)) {
1079 * The view is empty and scheme has been handled externally. When
1080 * user gets back from the external application he'd see blank page
1081 * and won't be able to navigate back. This happens when window.open
1082 * is used to handle schemes like sms/mms/mailto (for example in
1083 * WAC web standards tests: WS-15XX).
1085 * To solve the problem, the empty view is removed from the stack
1086 * and the previous one is shown. This is not an elegant solution
1087 * but we don't have a better one.
1089 LogInfo("Scheme has been handled externally. Removing empty view.");
1090 if (ewk_view_back_possible(This->m_currentEwkView)) {
1091 // go back to previous WKPage
1092 ewk_view_back(This->m_currentEwkView);
1094 // stop current WKPage
1095 ewk_view_stop(This->m_currentEwkView);
1096 ecore_idler_add(windowCloseIdlerCallback, This);
1101 ewk_policy_decision_ignore(policyDecision);
1105 void ViewLogic::policyNewWindowDecideCallback(
1107 Evas_Object* /*obj*/,
1110 LogDebug("policyNewWindowDecideCallback called");
1112 ViewLogic* This = static_cast<ViewLogic*>(data);
1114 Ewk_Policy_Decision* policyDecision =
1115 static_cast<Ewk_Policy_Decision*>(eventInfo);
1117 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1121 This->m_currentEwkView))
1123 ewk_policy_decision_use(policyDecision);
1126 ewk_policy_decision_ignore(policyDecision);
1130 void ViewLogic::pageResponseDecideCallback(
1132 Evas_Object* /*obj*/,
1135 LogDebug("pageResponseDecideCallback called");
1137 ViewLogic* This = static_cast<ViewLogic*>(data);
1139 Ewk_Policy_Decision* policyDecision =
1140 static_cast<Ewk_Policy_Decision*>(eventInfo);
1141 Ewk_Policy_Decision_Type policyDecisionType =
1142 ewk_policy_decision_type_get(policyDecision);
1144 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1146 ewk_policy_decision_use(policyDecision);
1147 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1148 LogDebug("download");
1149 ewk_policy_decision_suspend(policyDecision);
1151 // get uri information
1152 const char* url = ewk_policy_decision_url_get(policyDecision);
1153 if (NULL == url || strlen(url) == 0) {
1154 LogDebug("url data is empty");
1155 ewk_policy_decision_use(policyDecision);
1158 LogDebug("url = [" << url << "]");
1160 // get content information
1161 const char* content =
1162 ewk_policy_decision_response_mime_get(policyDecision);
1163 LogDebug("content type = [" << content << "]");
1165 // get cookie information
1166 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1167 LogDebug("cookie = [" << cookie << "]");
1169 LogDebug("Content not supported, will be opened in external app");
1170 This->m_appsSupport->downloadRequest(
1174 ewk_policy_decision_ignore(policyDecision);
1175 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1177 ewk_policy_decision_ignore(policyDecision);
1179 LogDebug("Type isn't handled");
1180 ewk_policy_decision_ignore(policyDecision);
1184 void ViewLogic::contextmenuCustomizeCallback(
1186 Evas_Object* /*obj*/,
1189 LogDebug("contextmenuCustomizeCallback called");
1192 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1193 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1194 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1195 (This->m_model->SettingList.Get().getContextMenu()
1196 == ContextMenu_Disable))
1198 LogDebug("ContextMenu Disable!!");
1199 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1200 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1203 ewk_context_menu_item_remove(menu, item);
1206 LogDebug("ContextMenu Enable!!");
1207 int menu_num = ewk_context_menu_item_count(menu);
1208 unsigned int idx = 0;
1210 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1216 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1219 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1220 ewk_context_menu_item_remove(menu, item);
1223 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
1224 ewk_context_menu_item_remove(menu, item);
1227 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
1228 ewk_context_menu_item_remove(menu, item);
1231 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_MEDIA_IN_NEW_WINDOW:
1232 ewk_context_menu_item_remove(menu, item);
1235 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1236 ewk_context_menu_item_remove(menu, item);
1243 } while (idx < menu_num);
1247 void ViewLogic::formSubmitCallback(
1249 Evas_Object* /*obj*/,
1252 LogDebug("formSubmitCallback called");
1254 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1256 const char* uri = ewk_form_data_url_get(formData);
1258 LogError("URL is empty");
1262 Eina_Hash* userData = ewk_form_data_values_get(formData);
1263 ViewModule::PasswordSupport::submitClicked(uri, userData);
1266 void ViewLogic::geolocationPermissionRequestCallback(
1268 Evas_Object* /*obj*/,
1272 ViewLogic* This = static_cast<ViewLogic*>(data);
1274 Ewk_Geolocation_Permission_Data* permissionRequest =
1275 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1277 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1278 SecurityOriginDB::FEATURE_GEOLOCATION)
1279 == WrtDB::SETTINGS_TYPE_OFF)
1281 ewk_geolocation_permission_request_allow_set(
1282 ewk_geolocation_permission_request_get(permissionRequest),
1286 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1288 This->m_securityOriginSupport->getSecurityOriginDAO(),
1292 void ViewLogic::notificationShowCallback(
1294 Evas_Object* /*obj*/,
1297 LogDebug("notificationShowCallback called");
1299 ViewLogic* This = static_cast<ViewLogic*>(data);
1302 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1304 using namespace ViewModule::WebNotification;
1306 WebNotificationDataPtr notiData(
1307 new WebNotificationData(
1309 ewk_notification_id_get(noti)));
1311 DPL::OptionalString string =
1312 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1313 if (!string.IsNull()) {
1314 notiData->m_iconURL = DPL::ToUTF8String(*string);
1316 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1317 if (!string.IsNull()) {
1318 notiData->m_title = DPL::ToUTF8String(*string);
1320 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1321 if (!string.IsNull()) {
1322 notiData->m_body = DPL::ToUTF8String(*string);
1325 LogInfo("notification id : " << notiData->m_id);
1326 LogInfo("notification iconURL : " << notiData->m_iconURL);
1327 LogInfo("notification title : " << notiData->m_title);
1328 LogInfo("notification body : " << notiData->m_body);
1330 showWebNotification(notiData);
1331 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1334 void ViewLogic::notificationCancelCallback(
1336 Evas_Object* /*obj*/,
1337 void* /*eventInfo*/)
1339 LogDebug("notificationCancelCallback called");
1342 void ViewLogic::notificationPermissionRequestCallback(
1344 Evas_Object* /*obj*/,
1347 LogDebug("notificationPermissionRequestCallback called");
1349 ViewLogic* This = static_cast<ViewLogic*>(data);
1350 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1351 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1352 == WrtDB::SETTINGS_TYPE_OFF)
1354 Ewk_Notification_Permission_Request* request =
1355 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1356 ewk_notification_permission_request_response(
1364 ViewModule::WebNotification::webNotificationPermissionRequest(
1366 This->m_securityOriginSupport->getSecurityOriginDAO(),
1372 void ViewLogic::vibrationVibrateCallback(uint64_t time, void* data)
1374 LogDebug("vibrationVibrateCallback called");
1376 ViewLogic* This = static_cast<ViewLogic*>(data);
1377 This->m_vibrationSupport->startVibration(static_cast<long>(time));
1381 void ViewLogic::vibrationCancelCallback(void* data)
1383 LogDebug("vibrationCancelCallback called");
1385 ViewLogic* This = static_cast<ViewLogic*>(data);
1387 This->m_vibrationSupport->stopVibration();
1392 // EWK Orientation Callback
1393 Eina_Bool ViewLogic::orientationLockCallback(
1395 Eina_Bool /*needLock*/,
1399 LogDebug("orientationLockCallback called");
1401 ViewLogic* This = static_cast<ViewLogic*>(data);
1403 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1404 LogDebug("orientation is portrait-primary");
1405 elm_win_rotation_with_resize_set(This->m_window, 0);
1406 ewk_view_orientation_send(obj, 0);
1407 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1408 LogDebug("orientation is landscape-primary");
1409 elm_win_rotation_with_resize_set(This->m_window, 270);
1410 ewk_view_orientation_send(obj, 90);
1411 } else if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1412 LogDebug("orientation is portrait-secondary");
1413 elm_win_rotation_with_resize_set(This->m_window, 180);
1414 ewk_view_orientation_send(obj, 180);
1415 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1416 LogDebug("orientation is landscape-secondary");
1417 elm_win_rotation_with_resize_set(This->m_window, 90);
1418 ewk_view_orientation_send(obj, -90);
1420 LogDebug("Wrong orientation is set");
1426 // Fullscreen API callbacks
1427 void ViewLogic::enterFullscreenCallback(
1429 Evas_Object* /*obj*/,
1430 void* /*eventInfo*/)
1432 LogInfo("enterFullscreenCallback called");
1434 ViewLogic* This = static_cast<ViewLogic*>(data);
1435 if (!This->m_cbs->toggleFullscreen.empty()) {
1436 This->m_cbs->toggleFullscreen(true);
1439 void ViewLogic::exitFullscreenCallback(
1441 Evas_Object* /*obj*/,
1442 void* /*eventInfo*/)
1444 LogInfo("exitFullscreenCallback called");
1446 ViewLogic* This = static_cast<ViewLogic*>(data);
1447 if (!This->m_cbs->toggleFullscreen.empty()) {
1448 This->m_cbs->toggleFullscreen(false);
1452 void ViewLogic::imeChangedCallback(
1454 Evas_Object* /*obj*/,
1460 ViewLogic* This = static_cast<ViewLogic*>(data);
1461 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1462 This->m_imeWidth = rect->w;
1463 This->m_imeHeight = rect->h;
1466 void ViewLogic::imeOpenedCallback(
1468 Evas_Object* /*obj*/,
1469 void* /*eventInfo*/)
1473 ViewLogic* This = static_cast<ViewLogic*>(data);
1475 using namespace WrtPlugins::W3C;
1476 SoftKeyboardChangeArgs args;
1477 args.state = IME_STATE_ON;
1478 args.width = This->m_imeWidth;
1479 args.height = This->m_imeHeight;
1480 This->fireJavascriptEvent(
1481 static_cast<int>(SoftKeyboardChangeCustomEvent),
1485 void ViewLogic::imeClosedCallback(
1487 Evas_Object* /*obj*/,
1488 void* /*eventInfo*/)
1492 ViewLogic* This = static_cast<ViewLogic*>(data);
1494 using namespace WrtPlugins::W3C;
1495 SoftKeyboardChangeArgs args;
1496 args.state = IME_STATE_OFF;
1498 This->fireJavascriptEvent(
1499 static_cast<int>(SoftKeyboardChangeCustomEvent),
1503 void ViewLogic::usermediaPermissionRequestCallback(
1505 Evas_Object* /*obj*/,
1508 LogDebug("usermediaPermissionRequestCallback called");
1510 ViewLogic* This = static_cast<ViewLogic*>(data);
1511 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1516 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1519 Ewk_Custom_Handlers_Data* handler =
1520 static_cast<Ewk_Custom_Handlers_Data*>(data);
1521 CustomHandlerDB::CustomHandlerPtr customHandler(
1522 new CustomHandlerDB::CustomHandler());
1523 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1525 LogDebug("base url: " << base_url);
1526 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1528 const char* url = ewk_custom_handlers_data_url_get(handler);
1530 LogDebug("url: " << url);
1531 customHandler->url = DPL::FromASCIIString(string(url));
1533 const char* target = ewk_custom_handlers_data_target_get(handler);
1535 LogDebug("target: " << target);
1536 customHandler->target = DPL::FromASCIIString(string(target));
1538 const char* title = ewk_custom_handlers_data_title_get(handler);
1540 LogDebug("title: " << title);
1541 customHandler->title = DPL::FromASCIIString(string(title));
1543 return customHandler;
1546 void ViewLogic::attachToCustomHandlersDao()
1548 if (!m_attachedToCustomHandlerDao) {
1549 CustomHandlerDB::Interface::attachDatabaseRW();
1553 void ViewLogic::detachFromCustomHandlersDao()
1555 if (m_attachedToCustomHandlerDao) {
1556 CustomHandlerDB::Interface::detachDatabase();
1560 const int protocolWhiteListLenth = 15;
1561 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1579 const int contentBlackListLenth = 14;
1580 char const * const contentBlackList[contentBlackListLenth] = {
1581 "application/x-www-form-urlencoded",
1582 "application/xhtml+xml",
1588 "multipart/x-mixed-replace",
1589 "text/cache-manifest",
1598 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1601 * @param customHandler
1603 void saveUserResponse(Wrt::Popup::PopupResponse response,
1604 CustomHandlerDB::CustomHandlerPtr customHandler)
1607 case Wrt::Popup::YES_DO_REMEMBER:
1608 LogDebug("User allowed, remember");
1609 customHandler->user_decision =
1610 static_cast<CustomHandlerDB::HandlerState>
1611 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1613 case Wrt::Popup::YES_DONT_REMEMBER:
1614 LogDebug("User allowed, don't remember");
1615 customHandler->user_decision = CustomHandlerDB::Agreed;
1617 case Wrt::Popup::NO_DO_REMEMBER:
1618 LogDebug("User didn't allow, remember");
1619 customHandler->user_decision =
1620 static_cast<CustomHandlerDB::HandlerState>
1621 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1623 case Wrt::Popup::NO_DONT_REMEMBER:
1624 LogDebug("User didn't allow, don't remember");
1625 customHandler->user_decision = CustomHandlerDB::Declined;
1630 //TODO registration, checking if registered and unregistration can be done in
1631 //common functions for both types of handlers. Only white and black lists
1632 //have to be separated
1633 //TODO attach database only one at the start (not in every callback?)
1634 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1640 CustomHandlerDB::CustomHandlerPtr customHandler =
1641 getCustomHandlerFromData(eventInfo);
1643 std::string scheme = DPL::ToUTF8String(customHandler->target);
1644 if (scheme.empty()) {
1645 LogError("No scheme provided");
1646 //TODO what about securityError?
1649 bool matched = false;
1650 //scheme on whiteList
1651 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1652 if (0 == strcmp(protocolWhiteList[i], scheme.c_str())) {
1653 LogDebug("Match found, protocol can be handled");
1658 //starts with web+ and have at least 5 chars (lowercase ASCII)
1659 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1660 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1661 //throw SecurityException
1667 if (c < 'a' || c > 'z') {
1668 LogWarning("Wrong char inside scheme. "
1669 << "Only lowercase ASCII letters accepted");
1670 //throw SecurityException
1677 ViewLogic* This = static_cast<ViewLogic*>(data);
1678 LogDebug("Creating handlers dao");
1679 This->attachToCustomHandlersDao();
1680 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1681 CustomHandlerDB::CustomHandlerPtr handler =
1682 handlersDao.getProtocolHandler(customHandler->target,
1684 customHandler->base_url);
1685 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1686 LogDebug("Protocol already registered - nothing to do");
1688 LogDebug("Protocol handler not found");
1689 Wrt::Popup::PopupResponse response =
1690 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1692 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1693 PROTOCOL_HANDLER_ASK_TITLE,
1694 PROTOCOL_HANDLER_ASK_MSG,
1695 PROTOCOL_HANDLER_ASK_REMEMBER);
1696 saveUserResponse(response, customHandler);
1697 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1700 handlersDao.registerProtocolHandler(*(customHandler.get()));
1701 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1702 //TODO remove old default handler somehow from appsvc
1703 LogDebug("Registering appservice entry");
1704 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1707 customHandler->target).c_str(),
1708 DPL::ToUTF8String(This->m_model->
1710 if (APPSVC_RET_OK != ret) {
1711 LogWarning("Appsvc entry failed: " << ret);
1714 LogDebug("Protocal saved");
1717 This->detachFromCustomHandlersDao();
1720 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1725 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(
1727 ViewLogic* This = static_cast<ViewLogic*>(data);
1728 LogDebug("Creating handlers dao");
1729 This->attachToCustomHandlersDao();
1730 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1731 CustomHandlerDB::CustomHandlerPtr handler =
1732 handlersDao.getProtocolHandler(customHandler->target,
1734 customHandler->base_url);
1736 if (handler->user_decision & CustomHandlerDB::Agreed) {
1737 ewk_custom_handlers_data_result_set(
1738 static_cast<Ewk_Custom_Handlers_Data*>(data),
1739 EWK_CUSTOM_HANDLERS_REGISTERED);
1741 ewk_custom_handlers_data_result_set(
1742 static_cast<Ewk_Custom_Handlers_Data*>(data),
1743 EWK_CUSTOM_HANDLERS_DECLINED);
1746 ewk_custom_handlers_data_result_set(
1747 static_cast<Ewk_Custom_Handlers_Data*>(data),
1748 EWK_CUSTOM_HANDLERS_NEW);
1750 This->detachFromCustomHandlersDao();
1753 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1758 CustomHandlerDB::CustomHandlerPtr customHandler =
1759 getCustomHandlerFromData(eventInfo);
1760 ViewLogic* This = static_cast<ViewLogic*>(data);
1761 LogDebug("Creating handlers dao");
1762 This->attachToCustomHandlersDao();
1763 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1764 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1765 handlersDao.getProtocolHandler(customHandler->target,
1767 customHandler->base_url);
1769 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1770 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1773 handlersDao.unregisterProtocolHandler(customHandler->target,
1775 customHandler->base_url);
1777 LogDebug("Nothing to unregister");
1780 This->detachFromCustomHandlersDao();
1783 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1789 CustomHandlerDB::CustomHandlerPtr customHandler =
1790 getCustomHandlerFromData(eventInfo);
1792 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1793 if (mimeType.empty()) {
1794 LogError("No mimeType provided.");
1797 for (int i = 0; i < contentBlackListLenth; ++i) {
1798 if (0 == strcmp(contentBlackList[i], mimeType.c_str())) {
1799 LogWarning("mimeType blacklisted");
1800 //throw SecurityException
1805 ViewLogic* This = static_cast<ViewLogic*>(data);
1806 LogDebug("Creating handlers dao");
1807 This->attachToCustomHandlersDao();
1808 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1809 CustomHandlerDB::CustomHandlerPtr handler =
1810 handlersDao.getContentHandler(customHandler->target,
1812 customHandler->base_url);
1813 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1814 LogDebug("Protocol already registered - nothing to do");
1816 LogDebug("Protocol handler not found");
1817 Wrt::Popup::PopupResponse response =
1818 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1820 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1821 CONTENT_HANDLER_ASK_TITLE,
1822 CONTENT_HANDLER_ASK_MSG,
1823 CONTENT_HANDLER_AKS_REMEMBER);
1824 saveUserResponse(response, customHandler);
1825 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1828 handlersDao.registerContentHandler(*(customHandler.get()));
1829 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1830 //TODO remove old default handler somehow from appsvc
1831 LogDebug("Registering appservice entry");
1832 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1834 customHandler->target).c_str(),
1836 DPL::ToUTF8String(This->m_model->
1838 if (APPSVC_RET_OK != ret) {
1839 LogWarning("Appsvc entry failed: " << ret);
1842 LogDebug("Content saved");
1844 This->detachFromCustomHandlersDao();
1847 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1852 CustomHandlerDB::CustomHandlerPtr customHandler =
1853 getCustomHandlerFromData(eventInfo);
1854 ViewLogic* This = static_cast<ViewLogic*>(data);
1855 LogDebug("Creating handlers dao");
1857 This->attachToCustomHandlersDao();
1858 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1859 CustomHandlerDB::CustomHandlerPtr handler =
1860 handlersDao.getContentHandler(customHandler->target,
1862 customHandler->base_url);
1864 if (handler->user_decision & CustomHandlerDB::Agreed) {
1865 ewk_custom_handlers_data_result_set(
1866 static_cast<Ewk_Custom_Handlers_Data*>(data),
1867 EWK_CUSTOM_HANDLERS_REGISTERED);
1869 ewk_custom_handlers_data_result_set(
1870 static_cast<Ewk_Custom_Handlers_Data*>(data),
1871 EWK_CUSTOM_HANDLERS_DECLINED);
1874 ewk_custom_handlers_data_result_set(
1875 static_cast<Ewk_Custom_Handlers_Data*>(data),
1876 EWK_CUSTOM_HANDLERS_NEW);
1878 This->detachFromCustomHandlersDao();
1881 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1886 CustomHandlerDB::CustomHandlerPtr customHandler =
1887 getCustomHandlerFromData(eventInfo);
1888 ViewLogic* This = static_cast<ViewLogic*>(data);
1889 LogDebug("Creating handlers dao");
1890 This->attachToCustomHandlersDao();
1891 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1892 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1893 handlersDao.getContentHandler(customHandler->target,
1895 customHandler->base_url);
1897 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1898 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1901 handlersDao.unregisterContentHandler(customHandler->target,
1903 customHandler->base_url);
1905 LogDebug("Nothing to unregister");
1907 This->detachFromCustomHandlersDao();
1910 void ViewLogic::didRunJavaScriptCallback(
1911 Evas_Object* /*obj*/,
1915 LogInfo("didRunJavaScriptCallback called");
1916 LogInfo("result = " << result);
1919 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1921 LogDebug("closeIdlerCallback");
1922 ViewLogic* This = static_cast<ViewLogic*>(data);
1923 This->windowClose();
1924 return ECORE_CALLBACK_CANCEL;
1927 int ViewLogic::appcoreLowMemoryCallback(void *data)
1929 LogInfo("appcoreLowMemoryCallback");
1931 ViewLogic* This = static_cast<ViewLogic*>(data);
1933 if (NULL == This->m_ewkContext) {
1934 LogInfo("ewk isn't initialize at this moment");
1936 // Crash may occur on specific situation
1937 // So use the followings after they become stable
1938 //ewk_context_cache_clear(This->m_ewkContext);
1939 //ewk_context_notify_low_memory(This->m_ewkContext);
1945 void ViewLogic::databaseUsagePermissionRequestCallback(
1947 Evas_Object* /*obj*/,
1950 LogDebug("databaseUsagePermissionRequestCallback called");
1952 ViewLogic* This = static_cast<ViewLogic*>(data);
1955 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1956 SecurityOriginDB::FEATURE_WEB_DATABASE)
1957 == WrtDB::SETTINGS_TYPE_OFF)
1959 // default value is deny
1962 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1964 This->m_securityOriginSupport->getSecurityOriginDAO(),
1969 void ViewLogic::fileSystemPermissionRequestCallback(
1971 Evas_Object* /*obj*/,
1974 LogDebug("fileSystemPermissionRequestCallback called");
1976 ViewLogic* This = static_cast<ViewLogic*>(data);
1978 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1979 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
1980 == WrtDB::SETTINGS_TYPE_OFF)
1982 Ewk_Context_File_System_Permission* fileSystemPermission =
1983 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
1984 ewk_context_file_system_permission_allow_set(fileSystemPermission,
1990 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1992 This->m_securityOriginSupport->getSecurityOriginDAO(),
1996 void ViewLogic::certificateConfirmRequestCallback(
1998 Evas_Object* /*obj*/,
2001 LogDebug("certificateConfirmRequestCallback called");
2004 ViewLogic* This = static_cast<ViewLogic*>(data);
2006 Ewk_Certificate_Policy_Decision* certificatePolicyDecision =
2007 static_cast<Ewk_Certificate_Policy_Decision*>(eventInfo);
2009 bool status = This->askUserForCertificateConfirm();
2011 ewk_certificate_policy_decision_allowed_set(
2012 certificatePolicyDecision,
2015 ewk_certificate_policy_decision_allowed_set(
2016 certificatePolicyDecision,
2021 bool ViewLogic::askUserForCertificateConfirm()
2023 return Wrt::Popup::PopupInvoker().askYesNo(
2024 CERTIFICATE_CONFIRM_REQUEST_ASK_TITLE,
2025 CERTIFICATE_CONFIRM_REQUEST_ASK_BODY);
2028 void ViewLogic::didRecieveMessageFromInjectedBundle(
2030 const char* /*body*/)
2032 LogDebug("did recive message " << name);
2035 void ViewLogic::didReceiveSynchronousMessage(
2040 LogDebug("didReceiveSynchronousMessage called");
2045 LogDebug("body is empty");
2049 if (!strcmp(name, uriBlockedMessageName)) {
2050 LogDebug("received : " << uriBlockedMessageName);
2051 // Currently WebProcess informs obly about blocked
2052 // URI - URI localization and security chekcs are
2053 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2054 // and bundle_uri_handling.cpp)
2055 rememberBlockedURI(DPL::FromUTF8String(body));
2057 } else if (!strcmp(name, uriChangedMessageName)) {
2058 LogDebug("received : " << uriChangedMessageName);
2059 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2060 *returnData = strdup(ret.c_str());
2064 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2066 m_blockedUri = DPL::ToUTF8String(inputURI);
2067 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2071 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2073 using namespace ViewModule::SecuritySupport;
2075 std::string url = DPL::ToUTF8String(changedURL);
2076 LogInfo("URL = [" << url << "]");
2079 // If url is same to URICHANGE_BLOCKED_URL,
2080 // this url has been already blocked by willsend.
2081 // So current page should be moved to previous page
2082 if (url == URICHANGE_BLOCKED_URL) {
2083 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2084 // block this page and open it in browser
2085 LogDebug("Request was blocked by WARP: " << url.c_str());
2086 if (!m_blockedUri.empty()) {
2087 LogDebug("open browser : " << m_blockedUri);
2088 bundle* bundleData = bundle_create();
2089 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2090 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2091 CONTROLLER_POST_EVENT(
2092 ApplicationLauncher,
2093 ApplicationLauncherEvents::LaunchApplicationByAppService(
2097 m_blockedUri = std::string();
2100 if (ewk_view_back_possible(m_currentEwkView)) {
2101 // go back to previous page
2102 ewk_view_back(m_currentEwkView);
2104 // stop current page
2105 ewk_view_stop(m_currentEwkView);
2106 ecore_idler_add(windowCloseIdlerCallback, this);
2109 // This is used in case of returning previous page
2111 return URICHANGE_PLUGIN_NO_CHANGE;
2116 // Check if this url with 'http' or 'https' is included in whitelist,
2117 // which has lists of accessible external documents and
2118 // used for ONLY Tizen app
2119 std::string matchedScheme;
2120 std::string matchedUri;
2121 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2124 ViewModule::Scheme scheme(matchedScheme);
2125 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2126 scheme.GetType() == ViewModule::Scheme::HTTPS)
2128 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2129 if (!checkWhitelist(url.c_str())) {
2130 LogInfo("This uri is not included in white document list");
2131 return URICHANGE_PLUGIN_STOP_ONLY;
2133 LogInfo("This url is included in WhiteList");
2135 // For WAC app, WRT should block access of device api
2136 // for external documents
2137 return URICHANGE_PLUGIN_STOP_ONLY;
2141 // register javascript object for plugins to be used
2142 LogInfo("Register Plugin Objects");
2143 return URICHANGE_PLUGIN_RESTART;
2146 void ViewLogic::windowClose()
2148 LogDebug("windowClose");
2149 Assert(m_closedEwkView && "no closed webview");
2151 if (1 >= m_ewkViewList.size()) {
2152 if (!m_cbs->webkitExit.empty()) {
2153 m_cbs->webkitExit();
2156 // call user callbacks
2157 if (!m_cbs->bufferUnset.empty()) {
2158 m_cbs->bufferUnset(m_currentEwkView);
2160 if (!m_cbs->windowClose.empty()) {
2161 m_cbs->windowClose(m_closedEwkView);
2163 removeEwkView(m_closedEwkView);
2165 // get latest ewkView
2166 m_currentEwkView = m_ewkViewList.back();
2167 const char* uri = ewk_view_url_get(m_currentEwkView);
2168 if (NULL == uri || 0 == strlen(uri)) {
2169 m_currentUri.clear();
2175 /* In case we support many pages in parallel
2176 * then view is not suspended*/
2177 //resumeEwkView(m_currentEwkView);
2180 if (!m_cbs->bufferSet.empty()) {
2181 m_cbs->bufferSet(m_currentEwkView);