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>
36 #include <widget_model.h>
37 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
38 #include <dpl/wrt-dao-ro/vconf_config.h>
39 #include <dpl/utils/wrt_global_settings.h>
41 #include <common/application_data.h>
42 #include <common/application_launcher.h>
43 #include <common/scheme.h>
45 #include <common/view_logic_apps_support.h>
46 #include <common/view_logic_custom_header_support.h>
47 #include <common/view_logic_password_support.h>
48 #include <common/view_logic_security_support.h>
49 #include <common/view_logic_security_origin_support.h>
50 #include <common/view_logic_storage_support.h>
51 #include <common/view_logic_uri_support.h>
52 #include <common/view_logic_user_agent_support.h>
53 #include <common/view_logic_vibration_support.h>
54 #include <view_logic_scheme_support.h>
55 #include <view_logic_filesystem_support.h>
56 #include <view_logic_geolocation_support_webkit2.h>
57 #include <view_logic_usermedia_support.h>
58 #include <view_logic_web_notification_support.h>
59 #include <view_logic_web_storage_support.h>
60 #include "bundles/plugin_module_support.h"
61 #include <popup-runner/PopupInvoker.h>
64 #include <js_overlay_types.h>
65 #include <i_runnable_widget_object.h>
66 #include <profiling_util.h>
67 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
68 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
69 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
70 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
71 #include <popup-runner/PopupInvoker.h>
73 #include <appsvc/appsvc.h>
76 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
77 const char * const uriBlockedMessageName = "uri_block_msg";
78 const char * const uriChangedMessageName = "uri_changed_msg";
79 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
80 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
81 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
82 const char * const URICHANGE_BLOCKED_URL = "null";
83 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
84 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
86 const char * const IME_STATE_ON = "on";
87 const char * const IME_STATE_OFF = "off";
89 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
90 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
91 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
92 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
93 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
94 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
95 const char * const CERTIFICATE_CONFIRM_REQUEST_ASK_TITLE =
97 const char * const CERTIFICATE_CONFIRM_REQUEST_ASK_BODY =
98 "This site's security certificate is not trusted! Do you acess this site?";
100 const wchar_t* BACKGROUND_ENABLED = L"background_enabled";
101 } // anonymous namespace
103 std::map<const std::string,
104 const Evas_Smart_Cb> ViewLogic::m_ewkCallbacksMap = {
105 { "load,started", &ViewLogic::loadStartedCallback },
106 { "load,finished", &ViewLogic::loadFinishedCallback },
107 { "title,changed", &ViewLogic::titleChangedCallback },
108 { "load,progress", &ViewLogic::loadProgressCallback },
109 { "load,progress,finished", &ViewLogic::loadProgressFinishedCallback },
110 { "process,crashed", &ViewLogic::processCrashedCallback },
112 { "create,window", &ViewLogic::createWindowCallback },
113 { "close,window", &ViewLogic::closeWindowCallback },
114 // WKPagePolicyClient
115 { "policy,navigation,decide", &ViewLogic::policyNavigationDecideCallback },
116 { "policy,newwindow,decide", &ViewLogic::policyNewWindowDecideCallback },
117 { "policy,response,decide", &ViewLogic::pageResponseDecideCallback },
118 // WKPageContextMenuClient
119 { "contextmenu,customize", &ViewLogic::contextmenuCustomizeCallback },
121 { "form,submit", &ViewLogic::formSubmitCallback },
122 // EWK Geolocation Callback
123 { "request,geolocation,permission",
124 &ViewLogic::geolocationPermissionRequestCallback },
125 // EWK Notification Callback
126 { "notification,show", &ViewLogic::notificationShowCallback },
127 { "notification,cancel", &ViewLogic::notificationCancelCallback },
128 { "notification,permission,request",
129 &ViewLogic::notificationPermissionRequestCallback },
131 { "database,quota,exceeded",
132 &ViewLogic::databaseUsagePermissionRequestCallback },
133 { "filesystem,permission,request",
134 &ViewLogic::fileSystemPermissionRequestCallback },
135 { "fullscreen,enterfullscreen", &ViewLogic::enterFullscreenCallback },
136 { "fullscreen,exitfullscreen", &ViewLogic::exitFullscreenCallback },
138 // when ime start to be showed on the webview,
139 // this callback will be called
140 { "inputmethod,changed", &ViewLogic::imeChangedCallback },
141 // this callback will be called
142 // when ime finishes to be showed on the webview
143 // "event_info" arg of this callback is always NULL point
144 // if web content should know size of ime,
145 // use "inputmethod,changed" instead of this.
147 { "editorclient,ime,opened", &ViewLogic::imeOpenedCallback },
148 // when ime finished to be hidden,
149 // this callback will be called
150 { "editorclient,ime,closed", &ViewLogic::imeClosedCallback },
151 // EWK Usermedia Callback
152 { "usermedia,permission,request",
153 &ViewLogic::usermediaPermissionRequestCallback },
155 { "protocolhandler,registration,requested",
156 &ViewLogic::protocolHandlerRegistrationCallback },
157 { "protocolhandler,isregistered",
158 &ViewLogic::protocolHandlerIsRegisteredCallback },
159 { "protocolhandler,unregistration,requested",
160 &ViewLogic::protocolHandlerUnregistrationCallback },
161 { "contenthandler,registration,requested",
162 &ViewLogic::contentHandlerRegistrationCallback },
163 { "contenthandler,isregistered",
164 &ViewLogic::contentHandlerIsRegisteredCallback },
165 { "contenthandler,unregistration,requested",
166 &ViewLogic::contentHandlerUnregistrationCallback },
167 { "request,certificate,confirm",
168 &ViewLogic::certificateConfirmRequestCallback }
171 ViewLogic::ViewLogic() :
176 m_cbs(new WRT::UserDelegates),
177 m_isBackgroundReload(false),
178 m_isBackgroundSupport(false),
179 m_appsSupport(new ViewModule::AppsSupport()),
180 m_vibrationSupport(new ViewModule::VibrationSupport()),
181 m_attachedToCustomHandlerDao(false)
183 ApplicationLauncherSingleton::Instance().Touch();
186 ViewLogic::~ViewLogic()
188 detachFromCustomHandlersDao();
191 bool ViewLogic::createWebView(Ewk_Context* context,
195 if (!context || !window) {
200 const char *theme = elm_theme_get(NULL);
203 LogInfo("theme is " << m_theme);
207 m_ewkContext = context;
210 Evas* canvas = evas_object_evas_get(m_window);
211 return createEwkView(canvas);
214 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
216 LogDebug("View prepare");
220 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
221 Assert(NULL != m_ewkContext);
224 ADD_PROFILING_POINT("initializeSupport", "start");
226 ADD_PROFILING_POINT("initializeSupport", "stop");
228 ewkClientInit(m_currentEwkView);
229 ADD_PROFILING_POINT("prepareEwkView", "start");
230 prepareEwkView(m_currentEwkView);
231 ADD_PROFILING_POINT("prepareEwkView", "stop");
232 initializePluginLoading();
235 void ViewLogic::showWidget()
237 LogDebug("showing widget");
238 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
239 if (m_currentUri.empty()) {
240 LogError("Localized current URI doesn't exist");
244 LogInfo("m_currentUri: " << m_currentUri);
247 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
249 if (!m_cbs->bufferSet.empty()) {
250 m_cbs->bufferSet(m_currentEwkView);
254 void ViewLogic::hideWidget()
256 LogDebug("hiding widget");
257 ViewModule::StorageSupport::deinitializeStorage(m_model);
258 m_appsSupport->deinitialize();
260 m_vibrationSupport->deinitialize();
262 while (m_ewkViewList.size()) {
263 LogInfo("pop webview: " << m_ewkViewList.back());
264 removeEwkView(m_ewkViewList.back());
266 m_ewkViewList.clear();
269 void ViewLogic::suspendWidget()
271 LogInfo("Pausing widget");
274 LogDebug("Request bundle to suspend");
275 PluginModuleSupport::suspend(m_ewkContext);
277 if (!m_currentEwkView) {
278 LogWarning("Cannot suspend widget without view");
280 setEwkViewInvisible(m_currentEwkView);
281 if (!m_isBackgroundSupport) {
282 suspendWebkit(m_currentEwkView);
286 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
288 // call user callback
289 if (!m_cbs->suspend.empty()) {
290 m_cbs->suspend(true);
294 void ViewLogic::resumeWidget()
296 LogInfo("Resume widget");
299 LogDebug("Request bundle to resume");
300 PluginModuleSupport::resume(m_ewkContext);
302 if (m_currentEwkView) {
303 setEwkViewVisible(m_currentEwkView);
304 if (!m_isBackgroundSupport) {
305 resumeWebkit(m_currentEwkView);
309 /* window system team recomend removing this win_raise code. */
312 * elm_win_raise(m_window);
315 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
317 // call user callback
318 if (!m_cbs->resume.empty()) {
323 void ViewLogic::resetWidget()
325 LogInfo("Resetting Widget");
327 // destory all webview
328 while (m_ewkViewList.size()) {
329 LogInfo("pop webview: " << m_ewkViewList.back());
330 removeEwkView(m_ewkViewList.back());
332 m_ewkViewList.clear();
334 // create new webview
335 createEwkView(evas_object_evas_get(m_window));
337 ewkClientInit(m_currentEwkView);
338 prepareEwkView(m_currentEwkView);
340 // check if current url is service url for this tizen service
341 std::string requestedUri =
342 ViewModule::UriSupport::getUri(m_model, m_startUrl);
343 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
344 DPL::FromUTF8String(requestedUri.c_str()),
347 initializePluginLoading();
350 PluginModuleSupport::resume(m_ewkContext);
351 m_currentUri = DPL::ToUTF8String(*servicedUri);
352 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
353 elm_win_activate(m_window);
354 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
356 // call user callback
357 if (!m_cbs->reset.empty()) {
360 if (!m_cbs->bufferSet.empty()) {
361 m_cbs->bufferSet(m_currentEwkView);
365 void ViewLogic::backward()
367 if (ewk_view_back_possible(m_currentEwkView)) {
368 ewk_view_back(m_currentEwkView);
370 if (1 >= m_ewkViewList.size()) {
371 // If there is no previous page, widget move to backgroud.
372 LogInfo("Widget move to backgroud");
373 elm_win_lower(m_window);
375 // Back to previous webview
376 LogInfo("Widget move to previous webview");
377 m_closedEwkView = m_currentEwkView;
378 ecore_idler_add(windowCloseIdlerCallback, this);
383 void ViewLogic::reloadStartPage()
385 LogInfo("Reload Start Page");
386 // prevent fail to load plugin bundle side
387 m_isBackgroundReload = true;
388 PluginModuleSupport::resume(m_ewkContext);
390 if (m_ewkViewList.size() != 0) {
391 while (m_ewkViewList.size() > 0) {
392 if (!m_cbs->bufferUnset.empty()) {
393 m_cbs->bufferUnset(m_currentEwkView);
395 removeEwkView(m_currentEwkView);
399 // create new webview
400 createEwkView(evas_object_evas_get(m_window));
401 ewkClientInit(m_currentEwkView);
404 prepareEwkView(m_currentEwkView);
405 initializePluginLoading();
408 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
411 if (!m_cbs->bufferSet.empty()) {
412 m_cbs->bufferSet(m_currentEwkView);
414 LogInfo("Reloading Start Page is done!");
417 Evas_Object* ViewLogic::getCurrentWebview()
419 LogInfo("get current webview");
420 return m_currentEwkView;
423 void ViewLogic::fireJavascriptEvent(int event, void* data)
425 PluginModuleSupport::dispatchJavaScriptEvent(
427 static_cast<WrtPlugins::W3C::CustomEventType>(event),
431 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
436 void ViewLogic::checkSyncMessageFromBundle(
441 LogDebug("didReceiveSynchronousMessage called");
446 LogDebug("body is empty");
450 if (!strcmp(name, uriBlockedMessageName)) {
451 LogDebug("received : " << uriBlockedMessageName);
452 // Currently WebProcess informs obly about blocked
453 // URI - URI localization and security chekcs are
454 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
455 // and bundle_uri_handling.cpp)
456 rememberBlockedURI(DPL::FromUTF8String(body));
458 } else if (!strcmp(name, uriChangedMessageName)) {
459 LogDebug("received : " << uriChangedMessageName);
460 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
461 *returnData = strdup(ret.c_str());
465 void ViewLogic::downloadData(const char* url)
472 m_appsSupport->downloadRequest(url, NULL, NULL);
475 void ViewLogic::activateVibration(bool on, uint64_t time)
479 m_vibrationSupport->startVibration(static_cast<long>(time));
481 m_vibrationSupport->stopVibration();
485 void ViewLogic::initializeSupport()
487 // background support
488 if (m_model->SettingList.Get().getBackgroundSupport()
489 == BackgroundSupport_Enable)
491 LogDebug("Background support enabled, set process active");
492 pid_t pid = getpid();
493 sysman_inform_active(pid);
494 m_isBackgroundSupport = true;
496 #ifndef DEPRECATED_SETTING_STRING
498 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
499 WrtDB::PropertyDAOReadOnly::WidgetPropertyValue bgEnableValue =
500 dao.getPropertyValue(DPL::String(BACKGROUND_ENABLED));
502 if (!bgEnableValue.IsNull() && !bgEnableValue->compare(L"true")) {
504 LogDebug("Background support enabled, set process active");
505 pid_t pid = getpid();
506 sysman_inform_active(pid);
507 m_isBackgroundSupport = true;
512 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
513 ViewModule::StorageSupport::initializeStorage(m_model);
514 m_appsSupport->initialize(m_model);
515 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
517 m_vibrationSupport->initialize();
520 void ViewLogic::initializePluginLoading()
522 // inform wrt information for plugin loading to web process
523 PluginModuleSupport::start(
526 elm_config_scale_get(),
527 ApplicationDataSingleton::Instance().getEncodedBundle(),
529 m_model->SettingList.Get().isEncrypted());
532 void ViewLogic::ewkClientInit(Evas_Object *wkView)
534 Assert(NULL != wkView && "ewk_view not created at this point");
536 FOREACH(it, m_ewkCallbacksMap) {
537 evas_object_smart_callback_add(
543 // EWK Orientation Callback
544 ewk_view_orientation_lock_callback_set(
546 orientationLockCallback,
550 void ViewLogic::ewkClientDeinit(Evas_Object *wkView)
552 LogDebug("ewkClientDeinit");
553 Assert(NULL != wkView && "ewk_view not created at this point");
555 FOREACH(it, m_ewkCallbacksMap) {
556 evas_object_smart_callback_del(
561 ewk_view_orientation_lock_callback_set(
567 bool ViewLogic::createEwkView(Evas* canvas)
569 LogDebug("createEwkVeiw");
571 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
572 Evas_Object* newEwkView = ewk_view_add_with_context(
575 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
578 LogError("View creation failed");
579 Wrt::Popup::PopupInvoker().showInfo(
580 "Info", "View creation failed", "close");
585 // even arguments pass the ewkContext, this API should be called
586 // after webkit Evas_Object is created
587 Ewk_Cookie_Manager *ewkCookieManager;
589 ewk_context_cookie_manager_get(m_ewkContext);
590 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
591 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
593 if (m_currentEwkView) {
594 setEwkViewInvisible(m_currentEwkView);
597 LogInfo("push webview: " << newEwkView);
598 m_ewkViewList.push_back(newEwkView);
599 m_currentEwkView = newEwkView;
603 void ViewLogic::setStartPage()
605 /* Start URI (as other uris) is now localized
606 * on WebProcess side */
607 m_currentUri = m_startUrl;
610 void ViewLogic::prepareEwkView(Evas_Object *wkView)
612 LogDebug("prepareEwkView called");
614 Ewk_Settings* settings = ewk_view_settings_get(wkView);
617 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
618 if (customUserAgent.empty()) {
619 auto userAgentString =
620 ViewModule::UserAgentSupport::getUserAgentFromVconf();
621 if (!userAgentString.empty()) {
622 LogDebug("Setting user agent as: " << userAgentString);
623 ewk_view_user_agent_set(wkView, userAgentString.c_str());
626 LogDebug("Setting custom user agent as: " << customUserAgent);
627 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
630 // set custom header : language
631 using namespace ViewModule::CustomHeaderSupport;
632 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
633 if (!customHeaderString.empty()) {
634 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
635 LogDebug("custom value=[" << customHeaderString << "]");
636 ewk_view_custom_header_add(wkView,
637 ACCEPT_LANGUAGE.c_str(),
638 customHeaderString.c_str());
641 // webkit NPAPI plugins is always on in wrt
642 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
644 // The followings are not implemeted yet by webkit2
645 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
646 // ewk_view_mode_set();
647 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE,
649 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
650 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
651 // elm_webview_show_magnifier_set(EINA_FALSE);
652 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
653 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
654 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
656 // disable zoom option when user click the input field
657 // this option is useful with the normal website
658 // for the make user friendly, disable auto zoom in the webapp
659 // The followings are not implemeted yet by webkit2
660 // elm_webview_input_field_zoom_set(EINA_FALSE);
662 // set cookie database path
663 // The followings are not implemeted yet by webkit2
664 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
666 // set visibility to WebCore. This value will be used for html5.
667 // also, this value will be changed in the suspend, resume
668 // or create window, close window.
669 ewk_view_page_visibility_state_set(wkView,
670 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
674 void ViewLogic::removeEwkView(Evas_Object *wkView)
676 LogInfo("removeEwkView called");
678 Assert(0 != m_ewkViewList.size());
680 // unregister webview callbacks
681 ewkClientDeinit(wkView);
683 // suspend NPAPI plugin - Not implemented by Webkit2
684 // ewk_view_pause_or_resume_plugins();
685 evas_object_del(wkView);
686 m_ewkViewList.remove(wkView);
689 void ViewLogic::resumeEwkView(Evas_Object *wkView)
691 LogInfo("resumeEwkView called");
694 // register webview callback
695 ewkClientInit(wkView);
698 resumeWebkit(wkView);
703 void ViewLogic::suspendEwkView(Evas_Object *wkView)
705 LogInfo("suspendEwkView called");
709 suspendWebkit(wkView);
711 // unregister webview callbacks
712 ewkClientDeinit(wkView);
717 void ViewLogic::setEwkViewInvisible(Evas_Object *wkView)
719 LogInfo("setEwkViewInvisible called");
722 ewk_view_page_visibility_state_set(wkView,
723 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
725 ewk_view_visibility_set(wkView, EINA_FALSE);
728 void ViewLogic::setEwkViewVisible(Evas_Object *wkView)
730 LogInfo("setEwkViewVisible called");
733 ewk_view_page_visibility_state_set(wkView,
734 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
736 ewk_view_visibility_set(wkView, EINA_TRUE);
739 void ViewLogic::resumeWebkit(Evas_Object *wkView)
741 LogDebug("resumeWebkit");
744 // resume NPAPI plugin
745 // The followings are not implemeted yet by webkit2
746 // ewk_view_pause_or_resume_plugins(false);
747 // ewk_view_pause_or_resume_video_audio(false);
748 // ewk_view_javascript_resume();
749 // ewk_view_enable_render();
750 // ewk_view_reduce_plugins_frame_rate(false);
751 ewk_view_resume(wkView);
756 void ViewLogic::suspendWebkit(Evas_Object *wkView)
758 LogDebug("suspendWebkit");
761 // suspend the followings
762 // The followings are not implemeted yet by webkit2
763 // ewk_view_pause_or_resume_plugins(true);
764 // ewk_view_pause_or_resume_video_audio(true);
765 ewk_view_suspend(wkView);
770 void ViewLogic::loadStartedCallback(
775 LogDebug("loadStartedCallback called");
777 ViewLogic* This = static_cast<ViewLogic*>(data);
778 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
780 // call loadFinish callback to wrt-client
781 if (!This->m_cbs->loadStart.empty()) {
782 This->m_cbs->loadStart(obj);
786 void ViewLogic::loadFinishedCallback(
791 LogDebug("loadFinishedCallback called");
793 ViewLogic* This = static_cast<ViewLogic*>(data);
796 const char* url = ewk_view_url_get(This->m_currentEwkView);
797 if (NULL == url || strlen(url) == 0) {
798 LogError("url is empty");
800 DPL::OptionalString jsOptionalString =
801 ViewModule::PasswordSupport::jsForAutoFillData(url);
802 if (jsOptionalString.IsNull()) {
803 LogError("Fail to get JS String");
805 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
807 if (EINA_FALSE == ewk_view_script_execute(
808 This->m_currentEwkView,
810 didRunJavaScriptCallback,
813 LogError("JS for auto fill data failed.");
818 // call loadFinish callback to wrt-client
819 if (!This->m_cbs->loadFinish.empty()) {
820 This->m_cbs->loadFinish(obj);
823 // set only encoded bundle
824 double scale = elm_config_scale_get();
825 PluginModuleSupport::setCustomProperties(
828 ApplicationDataSingleton::Instance().getEncodedBundle());
829 // check if 'appsevice' event is registed at the current frames.
830 // If so, dispatch the event to frames.
831 PluginModuleSupport::dispatchJavaScriptEvent(
833 WrtPlugins::W3C::ServiceCustomEvent,
836 // In this case, widget is reloaded in the background.
837 // After finished load, bundle should disconnent callback.
838 if (This->m_isBackgroundReload) {
839 PluginModuleSupport::suspend(This->m_ewkContext);
840 ewk_view_suspend(This->m_currentEwkView);
841 This->m_isBackgroundReload = false;
845 void ViewLogic::titleChangedCallback(
847 Evas_Object* /*obj*/,
850 LogDebug("titleChangedCallback called");
852 ViewLogic* This = static_cast<ViewLogic*>(data);
854 const char* title = static_cast<char*>(eventInfo);
856 if (0 == strlen(title)) {
857 LogDebug("title data is empty");
860 LogDebug("Title = [" << title << "]");
861 This->m_schemeSupport->HandleTizenScheme(title,
863 This->m_currentEwkView);
866 void ViewLogic::loadProgressCallback(
868 Evas_Object* /*obj*/,
871 double* progress = static_cast<double*>(eventInfo);
872 LogDebug("didChangeProgressCallback progress = " << *progress);
875 void ViewLogic::loadProgressFinishedCallback(
877 Evas_Object* /*obj*/,
880 LogDebug("didFinishProgressCallback");
882 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
883 if (!view->m_cbs->progressFinish.empty()) {
884 view->m_cbs->progressFinish();
888 void ViewLogic::processCrashedCallback(
890 Evas_Object* /*obj*/,
893 LogInfo("processCrashedCallback");
895 ViewLogic const * const view =
896 static_cast<ViewLogic const * const>(data);
897 if (!view->m_cbs->webCrash.empty()) {
898 view->m_cbs->webCrash();
900 // This flag will be prevented exit() call in the Webkit side
901 if (NULL != eventInfo) {
902 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
906 void ViewLogic::createWindowCallback(
911 LogDebug("createWindowCallback");
913 ViewLogic* This = static_cast<ViewLogic*>(data);
915 // First, current webview should be handled by user callback
916 if (!This->m_cbs->bufferUnset.empty()) {
917 This->m_cbs->bufferUnset(obj);
920 // this can be set by executable for specific purpose
922 if (!This->m_cbs->windowCreateBefore.empty()) {
923 // 'obj' is parent webview object
924 This->m_cbs->windowCreateBefore(&canvas, obj);
927 canvas = evas_object_evas_get(This->m_window);
930 // create new ewkview
931 This->createEwkView(canvas);
932 Evas_Object* newEwkView = This->m_currentEwkView;
934 // initialize new ewkview
935 This->setStartPage();
936 This->ewkClientInit(newEwkView);
937 This->prepareEwkView(newEwkView);
939 // Specific jobs of child, parent webview are handled by each executable
940 if (!This->m_cbs->windowCreateAfter.empty()) {
941 // 'obj' is parent webview, 'newEwkView' is child webview
942 This->m_cbs->windowCreateAfter(obj, newEwkView);
945 // Lastly, new webview should be handled by user callback
946 if (!This->m_cbs->bufferSet.empty()) {
947 This->m_cbs->bufferSet(newEwkView);
949 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
952 void ViewLogic::closeWindowCallback(
957 LogDebug("closeWindowCallback");
958 ViewLogic* This = static_cast<ViewLogic*>(data);
959 This->m_closedEwkView = obj;
960 ecore_idler_add(windowCloseIdlerCallback, This);
963 void ViewLogic::policyNavigationDecideCallback(
965 Evas_Object* /*obj*/,
968 LogDebug("policyNavigationDecideCallback called");
970 ViewLogic* This = static_cast<ViewLogic*>(data);
972 Ewk_Policy_Decision* policyDecision =
973 static_cast<Ewk_Policy_Decision*>(eventInfo);
975 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
979 This->m_currentEwkView))
982 ewk_policy_decision_use(policyDecision);
984 // check whether this is new empty window
985 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
986 if (!activeUrl || 0 == strlen(activeUrl)) {
988 * The view is empty and scheme has been handled externally. When
989 * user gets back from the external application he'd see blank page
990 * and won't be able to navigate back. This happens when window.open
991 * is used to handle schemes like sms/mms/mailto (for example in
992 * WAC web standards tests: WS-15XX).
994 * To solve the problem, the empty view is removed from the stack
995 * and the previous one is shown. This is not an elegant solution
996 * but we don't have a better one.
998 LogInfo("Scheme has been handled externally. Removing empty view.");
999 if (ewk_view_back_possible(This->m_currentEwkView)) {
1000 // go back to previous WKPage
1001 ewk_view_back(This->m_currentEwkView);
1003 // stop current WKPage
1004 ewk_view_stop(This->m_currentEwkView);
1005 ecore_idler_add(windowCloseIdlerCallback, This);
1010 ewk_policy_decision_ignore(policyDecision);
1014 void ViewLogic::policyNewWindowDecideCallback(
1016 Evas_Object* /*obj*/,
1019 LogDebug("policyNewWindowDecideCallback called");
1021 ViewLogic* This = static_cast<ViewLogic*>(data);
1023 Ewk_Policy_Decision* policyDecision =
1024 static_cast<Ewk_Policy_Decision*>(eventInfo);
1026 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1030 This->m_currentEwkView))
1032 ewk_policy_decision_use(policyDecision);
1035 ewk_policy_decision_ignore(policyDecision);
1039 void ViewLogic::pageResponseDecideCallback(
1041 Evas_Object* /*obj*/,
1044 LogDebug("pageResponseDecideCallback called");
1046 ViewLogic* This = static_cast<ViewLogic*>(data);
1048 Ewk_Policy_Decision* policyDecision =
1049 static_cast<Ewk_Policy_Decision*>(eventInfo);
1050 Ewk_Policy_Decision_Type policyDecisionType =
1051 ewk_policy_decision_type_get(policyDecision);
1053 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1055 ewk_policy_decision_use(policyDecision);
1056 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1057 LogDebug("download");
1058 ewk_policy_decision_suspend(policyDecision);
1060 // get uri information
1061 const char* url = ewk_policy_decision_url_get(policyDecision);
1062 if (NULL == url || strlen(url) == 0) {
1063 LogDebug("url data is empty");
1064 ewk_policy_decision_use(policyDecision);
1067 LogDebug("url = [" << url << "]");
1069 // get content information
1070 const char* content =
1071 ewk_policy_decision_response_mime_get(policyDecision);
1072 LogDebug("content type = [" << content << "]");
1074 // get cookie information
1075 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1076 LogDebug("cookie = [" << cookie << "]");
1078 LogDebug("Content not supported, will be opened in external app");
1079 This->m_appsSupport->downloadRequest(
1083 ewk_policy_decision_ignore(policyDecision);
1084 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1086 ewk_policy_decision_ignore(policyDecision);
1088 LogDebug("Type isn't handled");
1089 ewk_policy_decision_ignore(policyDecision);
1093 void ViewLogic::contextmenuCustomizeCallback(
1095 Evas_Object* /*obj*/,
1098 LogDebug("contextmenuCustomizeCallback called");
1101 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1102 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1103 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1104 (This->m_model->SettingList.Get().getContextMenu()
1105 == ContextMenu_Disable))
1107 LogDebug("ContextMenu Disable!!");
1108 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1109 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1112 ewk_context_menu_item_remove(menu, item);
1115 LogDebug("ContextMenu Enable!!");
1116 int menu_num = ewk_context_menu_item_count(menu);
1117 unsigned int idx = 0;
1119 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1125 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1128 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1129 ewk_context_menu_item_remove(menu, item);
1132 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
1133 ewk_context_menu_item_remove(menu, item);
1136 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
1137 ewk_context_menu_item_remove(menu, item);
1140 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_MEDIA_IN_NEW_WINDOW:
1141 ewk_context_menu_item_remove(menu, item);
1144 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1145 ewk_context_menu_item_remove(menu, item);
1152 } while (idx < menu_num);
1156 void ViewLogic::formSubmitCallback(
1158 Evas_Object* /*obj*/,
1161 LogDebug("formSubmitCallback called");
1163 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1165 const char* uri = ewk_form_data_url_get(formData);
1167 LogError("URL is empty");
1171 Eina_Hash* userData = ewk_form_data_values_get(formData);
1172 ViewModule::PasswordSupport::submitClicked(uri, userData);
1175 void ViewLogic::geolocationPermissionRequestCallback(
1177 Evas_Object* /*obj*/,
1181 ViewLogic* This = static_cast<ViewLogic*>(data);
1183 Ewk_Geolocation_Permission_Data* permissionRequest =
1184 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1186 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1187 SecurityOriginDB::FEATURE_GEOLOCATION)
1188 == WrtDB::SETTINGS_TYPE_OFF)
1190 ewk_geolocation_permission_request_allow_set(
1191 ewk_geolocation_permission_request_get(permissionRequest),
1195 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1197 This->m_securityOriginSupport->getSecurityOriginDAO(),
1201 void ViewLogic::notificationShowCallback(
1203 Evas_Object* /*obj*/,
1206 LogDebug("notificationShowCallback called");
1208 ViewLogic* This = static_cast<ViewLogic*>(data);
1211 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1213 using namespace ViewModule::WebNotification;
1215 WebNotificationDataPtr notiData(
1216 new WebNotificationData(
1218 ewk_notification_id_get(noti)));
1220 DPL::OptionalString string =
1221 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1222 if (!string.IsNull()) {
1223 notiData->m_iconURL = DPL::ToUTF8String(*string);
1225 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1226 if (!string.IsNull()) {
1227 notiData->m_title = DPL::ToUTF8String(*string);
1229 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1230 if (!string.IsNull()) {
1231 notiData->m_body = DPL::ToUTF8String(*string);
1234 LogInfo("notification id : " << notiData->m_id);
1235 LogInfo("notification iconURL : " << notiData->m_iconURL);
1236 LogInfo("notification title : " << notiData->m_title);
1237 LogInfo("notification body : " << notiData->m_body);
1239 showWebNotification(notiData);
1240 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1243 void ViewLogic::notificationCancelCallback(
1245 Evas_Object* /*obj*/,
1246 void* /*eventInfo*/)
1248 LogDebug("notificationCancelCallback called");
1251 void ViewLogic::notificationPermissionRequestCallback(
1253 Evas_Object* /*obj*/,
1256 LogDebug("notificationPermissionRequestCallback called");
1258 ViewLogic* This = static_cast<ViewLogic*>(data);
1259 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1260 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1261 == WrtDB::SETTINGS_TYPE_OFF)
1263 Ewk_Notification_Permission_Request* request =
1264 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1265 ewk_notification_permission_request_response(
1273 ViewModule::WebNotification::webNotificationPermissionRequest(
1275 This->m_securityOriginSupport->getSecurityOriginDAO(),
1281 // EWK Orientation Callback
1282 Eina_Bool ViewLogic::orientationLockCallback(
1284 Eina_Bool /*needLock*/,
1288 LogDebug("orientationLockCallback called");
1290 ViewLogic* This = static_cast<ViewLogic*>(data);
1292 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1293 LogDebug("orientation is portrait-primary");
1294 elm_win_rotation_with_resize_set(This->m_window, 0);
1295 ewk_view_orientation_send(obj, 0);
1296 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1297 LogDebug("orientation is landscape-primary");
1298 elm_win_rotation_with_resize_set(This->m_window, 270);
1299 ewk_view_orientation_send(obj, 90);
1300 } else if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1301 LogDebug("orientation is portrait-secondary");
1302 elm_win_rotation_with_resize_set(This->m_window, 180);
1303 ewk_view_orientation_send(obj, 180);
1304 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1305 LogDebug("orientation is landscape-secondary");
1306 elm_win_rotation_with_resize_set(This->m_window, 90);
1307 ewk_view_orientation_send(obj, -90);
1309 LogDebug("Wrong orientation is set");
1315 // Fullscreen API callbacks
1316 void ViewLogic::enterFullscreenCallback(
1318 Evas_Object* /*obj*/,
1319 void* /*eventInfo*/)
1321 LogInfo("enterFullscreenCallback called");
1323 ViewLogic* This = static_cast<ViewLogic*>(data);
1324 if (!This->m_cbs->toggleFullscreen.empty()) {
1325 This->m_cbs->toggleFullscreen(true);
1328 void ViewLogic::exitFullscreenCallback(
1330 Evas_Object* /*obj*/,
1331 void* /*eventInfo*/)
1333 LogInfo("exitFullscreenCallback called");
1335 ViewLogic* This = static_cast<ViewLogic*>(data);
1336 if (!This->m_cbs->toggleFullscreen.empty()) {
1337 This->m_cbs->toggleFullscreen(false);
1341 void ViewLogic::imeChangedCallback(
1343 Evas_Object* /*obj*/,
1349 ViewLogic* This = static_cast<ViewLogic*>(data);
1350 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1351 This->m_imeWidth = rect->w;
1352 This->m_imeHeight = rect->h;
1355 void ViewLogic::imeOpenedCallback(
1357 Evas_Object* /*obj*/,
1358 void* /*eventInfo*/)
1362 ViewLogic* This = static_cast<ViewLogic*>(data);
1364 using namespace WrtPlugins::W3C;
1365 SoftKeyboardChangeArgs args;
1366 args.state = IME_STATE_ON;
1367 args.width = This->m_imeWidth;
1368 args.height = This->m_imeHeight;
1369 This->fireJavascriptEvent(
1370 static_cast<int>(SoftKeyboardChangeCustomEvent),
1374 void ViewLogic::imeClosedCallback(
1376 Evas_Object* /*obj*/,
1377 void* /*eventInfo*/)
1381 ViewLogic* This = static_cast<ViewLogic*>(data);
1383 using namespace WrtPlugins::W3C;
1384 SoftKeyboardChangeArgs args;
1385 args.state = IME_STATE_OFF;
1387 This->fireJavascriptEvent(
1388 static_cast<int>(SoftKeyboardChangeCustomEvent),
1392 void ViewLogic::usermediaPermissionRequestCallback(
1394 Evas_Object* /*obj*/,
1397 LogDebug("usermediaPermissionRequestCallback called");
1399 ViewLogic* This = static_cast<ViewLogic*>(data);
1400 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1405 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1408 Ewk_Custom_Handlers_Data* handler =
1409 static_cast<Ewk_Custom_Handlers_Data*>(data);
1410 CustomHandlerDB::CustomHandlerPtr customHandler(
1411 new CustomHandlerDB::CustomHandler());
1412 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1414 LogDebug("base url: " << base_url);
1415 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1417 const char* url = ewk_custom_handlers_data_url_get(handler);
1419 LogDebug("url: " << url);
1420 customHandler->url = DPL::FromASCIIString(string(url));
1422 const char* target = ewk_custom_handlers_data_target_get(handler);
1424 LogDebug("target: " << target);
1425 customHandler->target = DPL::FromASCIIString(string(target));
1427 const char* title = ewk_custom_handlers_data_title_get(handler);
1429 LogDebug("title: " << title);
1430 customHandler->title = DPL::FromASCIIString(string(title));
1432 return customHandler;
1435 void ViewLogic::attachToCustomHandlersDao()
1437 if (!m_attachedToCustomHandlerDao) {
1438 CustomHandlerDB::Interface::attachDatabaseRW();
1442 void ViewLogic::detachFromCustomHandlersDao()
1444 if (m_attachedToCustomHandlerDao) {
1445 CustomHandlerDB::Interface::detachDatabase();
1449 const int protocolWhiteListLenth = 15;
1450 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1468 const int contentBlackListLenth = 14;
1469 char const * const contentBlackList[contentBlackListLenth] = {
1470 "application/x-www-form-urlencoded",
1471 "application/xhtml+xml",
1477 "multipart/x-mixed-replace",
1478 "text/cache-manifest",
1487 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1490 * @param customHandler
1492 void saveUserResponse(Wrt::Popup::PopupResponse response,
1493 CustomHandlerDB::CustomHandlerPtr customHandler)
1496 case Wrt::Popup::YES_DO_REMEMBER:
1497 LogDebug("User allowed, remember");
1498 customHandler->user_decision =
1499 static_cast<CustomHandlerDB::HandlerState>
1500 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1502 case Wrt::Popup::YES_DONT_REMEMBER:
1503 LogDebug("User allowed, don't remember");
1504 customHandler->user_decision = CustomHandlerDB::Agreed;
1506 case Wrt::Popup::NO_DO_REMEMBER:
1507 LogDebug("User didn't allow, remember");
1508 customHandler->user_decision =
1509 static_cast<CustomHandlerDB::HandlerState>
1510 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1512 case Wrt::Popup::NO_DONT_REMEMBER:
1513 LogDebug("User didn't allow, don't remember");
1514 customHandler->user_decision = CustomHandlerDB::Declined;
1519 //TODO registration, checking if registered and unregistration can be done in
1520 //common functions for both types of handlers. Only white and black lists
1521 //have to be separated
1522 //TODO attach database only one at the start (not in every callback?)
1523 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1529 CustomHandlerDB::CustomHandlerPtr customHandler =
1530 getCustomHandlerFromData(eventInfo);
1532 std::string scheme = DPL::ToUTF8String(customHandler->target);
1533 if (scheme.empty()) {
1534 LogError("No scheme provided");
1535 //TODO what about securityError?
1538 bool matched = false;
1539 //scheme on whiteList
1540 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1541 if (0 == strcmp(protocolWhiteList[i], scheme.c_str())) {
1542 LogDebug("Match found, protocol can be handled");
1547 //starts with web+ and have at least 5 chars (lowercase ASCII)
1548 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1549 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1550 //throw SecurityException
1556 if (c < 'a' || c > 'z') {
1557 LogWarning("Wrong char inside scheme. "
1558 << "Only lowercase ASCII letters accepted");
1559 //throw SecurityException
1566 ViewLogic* This = static_cast<ViewLogic*>(data);
1567 LogDebug("Creating handlers dao");
1568 This->attachToCustomHandlersDao();
1569 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1570 CustomHandlerDB::CustomHandlerPtr handler =
1571 handlersDao.getProtocolHandler(customHandler->target,
1573 customHandler->base_url);
1574 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1575 LogDebug("Protocol already registered - nothing to do");
1577 LogDebug("Protocol handler not found");
1578 Wrt::Popup::PopupResponse response =
1579 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1581 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1582 PROTOCOL_HANDLER_ASK_TITLE,
1583 PROTOCOL_HANDLER_ASK_MSG,
1584 PROTOCOL_HANDLER_ASK_REMEMBER);
1585 saveUserResponse(response, customHandler);
1586 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1589 handlersDao.registerProtocolHandler(*(customHandler.get()));
1590 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1591 //TODO remove old default handler somehow from appsvc
1592 LogDebug("Registering appservice entry");
1593 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1596 customHandler->target).c_str(),
1597 DPL::ToUTF8String(This->m_model->
1599 if (APPSVC_RET_OK != ret) {
1600 LogWarning("Appsvc entry failed: " << ret);
1603 LogDebug("Protocal saved");
1606 This->detachFromCustomHandlersDao();
1609 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1614 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(
1616 ViewLogic* This = static_cast<ViewLogic*>(data);
1617 LogDebug("Creating handlers dao");
1618 This->attachToCustomHandlersDao();
1619 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1620 CustomHandlerDB::CustomHandlerPtr handler =
1621 handlersDao.getProtocolHandler(customHandler->target,
1623 customHandler->base_url);
1625 if (handler->user_decision & CustomHandlerDB::Agreed) {
1626 ewk_custom_handlers_data_result_set(
1627 static_cast<Ewk_Custom_Handlers_Data*>(data),
1628 EWK_CUSTOM_HANDLERS_REGISTERED);
1630 ewk_custom_handlers_data_result_set(
1631 static_cast<Ewk_Custom_Handlers_Data*>(data),
1632 EWK_CUSTOM_HANDLERS_DECLINED);
1635 ewk_custom_handlers_data_result_set(
1636 static_cast<Ewk_Custom_Handlers_Data*>(data),
1637 EWK_CUSTOM_HANDLERS_NEW);
1639 This->detachFromCustomHandlersDao();
1642 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1647 CustomHandlerDB::CustomHandlerPtr customHandler =
1648 getCustomHandlerFromData(eventInfo);
1649 ViewLogic* This = static_cast<ViewLogic*>(data);
1650 LogDebug("Creating handlers dao");
1651 This->attachToCustomHandlersDao();
1652 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1653 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1654 handlersDao.getProtocolHandler(customHandler->target,
1656 customHandler->base_url);
1658 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1659 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1662 handlersDao.unregisterProtocolHandler(customHandler->target,
1664 customHandler->base_url);
1666 LogDebug("Nothing to unregister");
1669 This->detachFromCustomHandlersDao();
1672 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1678 CustomHandlerDB::CustomHandlerPtr customHandler =
1679 getCustomHandlerFromData(eventInfo);
1681 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1682 if (mimeType.empty()) {
1683 LogError("No mimeType provided.");
1686 for (int i = 0; i < contentBlackListLenth; ++i) {
1687 if (0 == strcmp(contentBlackList[i], mimeType.c_str())) {
1688 LogWarning("mimeType blacklisted");
1689 //throw SecurityException
1694 ViewLogic* This = static_cast<ViewLogic*>(data);
1695 LogDebug("Creating handlers dao");
1696 This->attachToCustomHandlersDao();
1697 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1698 CustomHandlerDB::CustomHandlerPtr handler =
1699 handlersDao.getContentHandler(customHandler->target,
1701 customHandler->base_url);
1702 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1703 LogDebug("Protocol already registered - nothing to do");
1705 LogDebug("Protocol handler not found");
1706 Wrt::Popup::PopupResponse response =
1707 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1709 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1710 CONTENT_HANDLER_ASK_TITLE,
1711 CONTENT_HANDLER_ASK_MSG,
1712 CONTENT_HANDLER_AKS_REMEMBER);
1713 saveUserResponse(response, customHandler);
1714 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1717 handlersDao.registerContentHandler(*(customHandler.get()));
1718 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1719 //TODO remove old default handler somehow from appsvc
1720 LogDebug("Registering appservice entry");
1721 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1723 customHandler->target).c_str(),
1725 DPL::ToUTF8String(This->m_model->
1727 if (APPSVC_RET_OK != ret) {
1728 LogWarning("Appsvc entry failed: " << ret);
1731 LogDebug("Content saved");
1733 This->detachFromCustomHandlersDao();
1736 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1741 CustomHandlerDB::CustomHandlerPtr customHandler =
1742 getCustomHandlerFromData(eventInfo);
1743 ViewLogic* This = static_cast<ViewLogic*>(data);
1744 LogDebug("Creating handlers dao");
1746 This->attachToCustomHandlersDao();
1747 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1748 CustomHandlerDB::CustomHandlerPtr handler =
1749 handlersDao.getContentHandler(customHandler->target,
1751 customHandler->base_url);
1753 if (handler->user_decision & CustomHandlerDB::Agreed) {
1754 ewk_custom_handlers_data_result_set(
1755 static_cast<Ewk_Custom_Handlers_Data*>(data),
1756 EWK_CUSTOM_HANDLERS_REGISTERED);
1758 ewk_custom_handlers_data_result_set(
1759 static_cast<Ewk_Custom_Handlers_Data*>(data),
1760 EWK_CUSTOM_HANDLERS_DECLINED);
1763 ewk_custom_handlers_data_result_set(
1764 static_cast<Ewk_Custom_Handlers_Data*>(data),
1765 EWK_CUSTOM_HANDLERS_NEW);
1767 This->detachFromCustomHandlersDao();
1770 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1775 CustomHandlerDB::CustomHandlerPtr customHandler =
1776 getCustomHandlerFromData(eventInfo);
1777 ViewLogic* This = static_cast<ViewLogic*>(data);
1778 LogDebug("Creating handlers dao");
1779 This->attachToCustomHandlersDao();
1780 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1781 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1782 handlersDao.getContentHandler(customHandler->target,
1784 customHandler->base_url);
1786 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1787 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1790 handlersDao.unregisterContentHandler(customHandler->target,
1792 customHandler->base_url);
1794 LogDebug("Nothing to unregister");
1796 This->detachFromCustomHandlersDao();
1799 void ViewLogic::didRunJavaScriptCallback(
1800 Evas_Object* /*obj*/,
1804 LogInfo("didRunJavaScriptCallback called");
1805 LogInfo("result = " << result);
1808 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1810 LogDebug("closeIdlerCallback");
1811 ViewLogic* This = static_cast<ViewLogic*>(data);
1812 This->windowClose();
1813 return ECORE_CALLBACK_CANCEL;
1817 void ViewLogic::databaseUsagePermissionRequestCallback(
1819 Evas_Object* /*obj*/,
1822 LogDebug("databaseUsagePermissionRequestCallback called");
1824 ViewLogic* This = static_cast<ViewLogic*>(data);
1827 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1828 SecurityOriginDB::FEATURE_WEB_DATABASE)
1829 == WrtDB::SETTINGS_TYPE_OFF)
1831 // default value is deny
1834 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1836 This->m_securityOriginSupport->getSecurityOriginDAO(),
1841 void ViewLogic::fileSystemPermissionRequestCallback(
1843 Evas_Object* /*obj*/,
1846 LogDebug("fileSystemPermissionRequestCallback called");
1848 ViewLogic* This = static_cast<ViewLogic*>(data);
1850 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1851 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
1852 == WrtDB::SETTINGS_TYPE_OFF)
1854 Ewk_Context_File_System_Permission* fileSystemPermission =
1855 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
1856 ewk_context_file_system_permission_allow_set(fileSystemPermission,
1862 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1864 This->m_securityOriginSupport->getSecurityOriginDAO(),
1868 void ViewLogic::certificateConfirmRequestCallback(
1870 Evas_Object* /*obj*/,
1873 LogDebug("certificateConfirmRequestCallback called");
1876 ViewLogic* This = static_cast<ViewLogic*>(data);
1878 Ewk_Certificate_Policy_Decision* certificatePolicyDecision =
1879 static_cast<Ewk_Certificate_Policy_Decision*>(eventInfo);
1881 bool status = This->askUserForCertificateConfirm();
1883 ewk_certificate_policy_decision_allowed_set(
1884 certificatePolicyDecision,
1887 ewk_certificate_policy_decision_allowed_set(
1888 certificatePolicyDecision,
1893 bool ViewLogic::askUserForCertificateConfirm()
1895 return Wrt::Popup::PopupInvoker().askYesNo(
1896 CERTIFICATE_CONFIRM_REQUEST_ASK_TITLE,
1897 CERTIFICATE_CONFIRM_REQUEST_ASK_BODY);
1900 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
1902 m_blockedUri = DPL::ToUTF8String(inputURI);
1903 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
1907 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
1909 using namespace ViewModule::SecuritySupport;
1911 std::string url = DPL::ToUTF8String(changedURL);
1912 LogInfo("URL = [" << url << "]");
1915 // If url is same to URICHANGE_BLOCKED_URL,
1916 // this url has been already blocked by willsend.
1917 // So current page should be moved to previous page
1918 if (url == URICHANGE_BLOCKED_URL) {
1919 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1920 // block this page and open it in browser
1921 LogDebug("Request was blocked by WARP: " << url.c_str());
1922 if (!m_blockedUri.empty()) {
1923 LogDebug("open browser : " << m_blockedUri);
1924 bundle* bundleData = bundle_create();
1925 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
1926 appsvc_set_uri(bundleData, m_blockedUri.c_str());
1927 CONTROLLER_POST_EVENT(
1928 ApplicationLauncher,
1929 ApplicationLauncherEvents::LaunchApplicationByAppService(
1933 m_blockedUri = std::string();
1936 if (ewk_view_back_possible(m_currentEwkView)) {
1937 // go back to previous page
1938 ewk_view_back(m_currentEwkView);
1940 // stop current page
1941 ewk_view_stop(m_currentEwkView);
1942 ecore_idler_add(windowCloseIdlerCallback, this);
1945 // This is used in case of returning previous page
1947 return URICHANGE_PLUGIN_NO_CHANGE;
1952 // Check if this url with 'http' or 'https' is included in whitelist,
1953 // which has lists of accessible external documents and
1954 // used for ONLY Tizen app
1955 std::string matchedScheme;
1956 std::string matchedUri;
1957 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
1960 ViewModule::Scheme scheme(matchedScheme);
1961 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
1962 scheme.GetType() == ViewModule::Scheme::HTTPS)
1964 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1965 if (!checkWhitelist(url.c_str())) {
1966 LogInfo("This uri is not included in white document list");
1967 return URICHANGE_PLUGIN_STOP_ONLY;
1969 LogInfo("This url is included in WhiteList");
1971 // For WAC app, WRT should block access of device api
1972 // for external documents
1973 return URICHANGE_PLUGIN_STOP_ONLY;
1977 // register javascript object for plugins to be used
1978 LogInfo("Register Plugin Objects");
1979 return URICHANGE_PLUGIN_RESTART;
1982 void ViewLogic::windowClose()
1984 LogDebug("windowClose");
1985 Assert(m_closedEwkView && "no closed webview");
1987 if (1 >= m_ewkViewList.size()) {
1988 if (!m_cbs->webkitExit.empty()) {
1989 m_cbs->webkitExit();
1992 // call user callbacks
1993 if (!m_cbs->bufferUnset.empty()) {
1994 m_cbs->bufferUnset(m_currentEwkView);
1996 if (!m_cbs->windowClose.empty()) {
1997 m_cbs->windowClose(m_closedEwkView);
1999 removeEwkView(m_closedEwkView);
2001 // get latest ewkView
2002 m_currentEwkView = m_ewkViewList.back();
2003 const char* uri = ewk_view_url_get(m_currentEwkView);
2004 if (NULL == uri || 0 == strlen(uri)) {
2005 m_currentUri.clear();
2011 /* In case we support many pages in parallel
2012 * then view is not suspended*/
2013 //resumeEwkView(m_currentEwkView);
2014 setEwkViewVisible(m_currentEwkView);
2017 if (!m_cbs->bufferSet.empty()) {
2018 m_cbs->bufferSet(m_currentEwkView);