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" ;
103 } // anonymous namespace
105 std::map<const std::string, const Evas_Smart_Cb> ViewLogic::m_ewkCallbacksMap =
107 {"load,started", &ViewLogic::loadStartedCallback},
108 {"load,finished", &ViewLogic::loadFinishedCallback},
109 {"title,changed", &ViewLogic::titleChangedCallback},
110 {"load,progress", &ViewLogic::loadProgressCallback},
111 {"load,progress,finished", &ViewLogic::loadProgressFinishedCallback},
112 {"process,crashed", &ViewLogic::processCrashedCallback},
114 {"create,window", &ViewLogic::createWindowCallback},
115 {"close,window", &ViewLogic::closeWindowCallback},
116 // WKPagePolicyClient
117 {"policy,navigation,decide", &ViewLogic::policyNavigationDecideCallback},
118 {"policy,newwindow,decide", &ViewLogic::policyNewWindowDecideCallback},
119 {"policy,response,decide", &ViewLogic::pageResponseDecideCallback},
120 // WKPageContextMenuClient
121 {"contextmenu,customize", &ViewLogic::contextmenuCustomizeCallback},
123 {"form,submit", &ViewLogic::formSubmitCallback},
124 // EWK Geolocation Callback
125 {"request,geolocation,permission", &ViewLogic::geolocationPermissionRequestCallback},
126 // EWK Notification Callback
127 {"notification,show", &ViewLogic::notificationShowCallback},
128 {"notification,cancel", &ViewLogic::notificationCancelCallback},
129 {"notification,permission,request", &ViewLogic::notificationPermissionRequestCallback},
131 {"database,quota,exceeded", &ViewLogic::databaseUsagePermissionRequestCallback},
132 {"filesystem,permission,request", &ViewLogic::fileSystemPermissionRequestCallback},
133 {"fullscreen,enterfullscreen", &ViewLogic::enterFullscreenCallback},
134 {"fullscreen,exitfullscreen", &ViewLogic::exitFullscreenCallback},
136 // when ime start to be showed on the webview,
137 // this callback will be called
138 {"inputmethod,changed", &ViewLogic::imeChangedCallback},
139 // this callback will be called
140 // when ime finishes to be showed on the webview
141 // "event_info" arg of this callback is always NULL point
142 // if web content should know size of ime,
143 // use "inputmethod,changed" instead of this.
145 {"editorclient,ime,opened", &ViewLogic::imeOpenedCallback},
146 // when ime finished to be hidden,
147 // this callback will be called
148 {"editorclient,ime,closed", &ViewLogic::imeClosedCallback},
149 // EWK Usermedia Callback
150 {"usermedia,permission,request", &ViewLogic::usermediaPermissionRequestCallback},
152 {"protocolhandler,registration,requested", &ViewLogic::protocolHandlerRegistrationCallback},
153 {"protocolhandler,isregistered", &ViewLogic::protocolHandlerIsRegisteredCallback},
154 {"protocolhandler,unregistration,requested", &ViewLogic::protocolHandlerUnregistrationCallback},
155 {"contenthandler,registration,requested", &ViewLogic::contentHandlerRegistrationCallback},
156 {"contenthandler,isregistered", &ViewLogic::contentHandlerIsRegisteredCallback},
157 {"contenthandler,unregistration,requested", &ViewLogic::contentHandlerUnregistrationCallback},
158 {"request,certificate,confirm", &ViewLogic::certificateConfirmRequestCallback}
161 ViewLogic::ViewLogic():
166 m_cbs(new WRT::UserDelegates),
167 m_isBackgroundReload(false),
168 m_isBackgroundSupport(false),
169 m_appsSupport(new ViewModule::AppsSupport()),
170 m_vibrationSupport(new ViewModule::VibrationSupport()),
171 m_attachedToCustomHandlerDao(false)
175 ViewLogic::~ViewLogic ()
177 detachFromCustomHandlersDao();
180 bool ViewLogic::createWebView(Ewk_Context* context,
184 initializeEwkContext(context);
185 Assert(NULL != m_ewkContext);
188 if(!createEwkView(evas_object_evas_get(m_window)))
195 void ViewLogic::destroyWebView()
198 finalizeEwkContext();
202 void ViewLogic::initialize()
204 LogDebug("Initializing");
205 ApplicationLauncherSingleton::Instance().Touch();
206 appcore_set_event_callback(
207 APPCORE_EVENT_LOW_MEMORY,
208 &appcoreLowMemoryCallback,
212 void ViewLogic::terminate()
214 LogDebug("terminating view logic");
218 LogError("Widget model not created");
223 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
225 LogDebug("View prepare");
229 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
230 Assert(NULL != m_ewkContext);
233 ADD_PROFILING_POINT("initializeSupport", "start");
235 ADD_PROFILING_POINT("initializeSupport", "stop");
237 ewkClientInit(m_currentEwkView);
238 ADD_PROFILING_POINT("prepareEwkView", "start");
239 prepareEwkView(m_currentEwkView);
240 ADD_PROFILING_POINT("prepareEwkView", "stop");
241 initializePluginLoading();
244 void ViewLogic::showWidget()
246 LogDebug("showing widget");
247 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
248 if (m_currentUri.empty()) {
249 LogError("Localized current URI doesn't exist");
253 LogInfo("m_currentUri: " << m_currentUri);
256 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
258 if (!m_cbs->bufferSet.empty()) {
259 m_cbs->bufferSet(m_currentEwkView);
263 void ViewLogic::hideWidget()
265 LogDebug("hiding widget");
266 ViewModule::StorageSupport::deinitializeStorage(m_model);
267 m_appsSupport->deinitialize();
269 m_vibrationSupport->deinitialize();
271 while (m_ewkViewList.size()) {
272 LogInfo("pop webview: " << m_ewkViewList.back());
273 removeEwkView(m_ewkViewList.back());
275 m_ewkViewList.clear();
278 void ViewLogic::suspendWidget()
280 LogInfo("Pausing widget");
283 LogDebug("Request bundle to suspend");
284 PluginModuleSupport::suspend(m_ewkContext);
286 if (!m_currentEwkView) {
287 LogWarning("Cannot suspend widget without view");
289 setEwkViewInvisible(m_currentEwkView);
290 if (!m_isBackgroundSupport) {
291 suspendWebkit(m_currentEwkView);
295 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
297 // call user callback
298 if (!m_cbs->suspend.empty()) {
299 m_cbs->suspend(true);
303 void ViewLogic::resumeWidget()
305 LogInfo("Resume widget");
308 LogDebug("Request bundle to resume");
309 PluginModuleSupport::resume(m_ewkContext);
311 if (m_currentEwkView) {
312 setEwkViewVisible(m_currentEwkView);
313 if (!m_isBackgroundSupport) {
314 resumeWebkit(m_currentEwkView);
318 /* window system team recomend removing this win_raise code. */
321 elm_win_raise(m_window);
324 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
326 // call user callback
327 if (!m_cbs->resume.empty()) {
332 void ViewLogic::resetWidget()
334 LogInfo("Resetting Widget");
336 // destory all webview
337 while (m_ewkViewList.size()) {
338 LogInfo("pop webview: " << m_ewkViewList.back());
339 removeEwkView(m_ewkViewList.back());
341 m_ewkViewList.clear();
343 // create new webview
344 createEwkView(evas_object_evas_get(m_window));
346 ewkClientInit(m_currentEwkView);
347 prepareEwkView(m_currentEwkView);
349 // check if current url is service url for this tizen service
350 std::string requestedUri =
351 ViewModule::UriSupport::getUri(m_model, m_startUrl);
352 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
353 DPL::FromUTF8String(requestedUri.c_str()),
356 initializePluginLoading();
359 PluginModuleSupport::resume(m_ewkContext);
360 m_currentUri = DPL::ToUTF8String(*servicedUri);
361 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
362 elm_win_activate(m_window);
363 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
365 // call user callback
366 if (!m_cbs->reset.empty()) {
369 if (!m_cbs->bufferSet.empty()) {
370 m_cbs->bufferSet(m_currentEwkView);
374 void ViewLogic::backward()
376 if (ewk_view_back_possible(m_currentEwkView)) {
377 ewk_view_back(m_currentEwkView);
379 if (1 >= m_ewkViewList.size()) {
380 // If there is no previous page, widget move to backgroud.
381 LogInfo("Widget move to backgroud");
382 elm_win_lower(m_window);
384 // Back to previous webview
385 LogInfo("Widget move to previous webview");
386 m_closedEwkView = m_currentEwkView;
387 ecore_idler_add(windowCloseIdlerCallback, this);
392 void ViewLogic::reloadStartPage()
394 LogInfo("Reload Start Page");
395 // prevent fail to load plugin bundle side
396 m_isBackgroundReload = true;
397 PluginModuleSupport::resume(m_ewkContext);
399 if (m_ewkViewList.size() != 0) {
400 while (m_ewkViewList.size() > 0) {
401 if (!m_cbs->bufferUnset.empty()) {
402 m_cbs->bufferUnset(m_currentEwkView);
404 removeEwkView(m_currentEwkView);
408 // create new webview
409 createEwkView(evas_object_evas_get(m_window));
410 ewkClientInit(m_currentEwkView);
413 prepareEwkView(m_currentEwkView);
414 initializePluginLoading();
417 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
420 if (!m_cbs->bufferSet.empty()) {
421 m_cbs->bufferSet(m_currentEwkView);
423 LogInfo("Reloading Start Page is done!");
426 Evas_Object* ViewLogic::getCurrentWebview()
428 LogInfo("get current webview");
429 return m_currentEwkView;
432 void ViewLogic::fireJavascriptEvent(int event, void* data)
434 PluginModuleSupport::dispatchJavaScriptEvent(
436 static_cast<WrtPlugins::W3C::CustomEventType>(event),
440 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
445 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
447 LogInfo("initializeEwkContext called");
448 Assert(newEwkContext && "Ewk_Context provided can not be null");
449 // bundle callback setting
450 ewk_context_message_from_injected_bundle_callback_set(
452 contextMessageFromInjectedBundleCallback,
453 static_cast<void*>(this));
455 // proxy server setting
456 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
457 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
458 || (strstr(proxyAddress, "0.0.0.0")))
460 LogInfo("proxy address is empty");
461 ewk_context_proxy_uri_set(newEwkContext, NULL);
463 LogInfo("proxy address [" << proxyAddress << "]");
464 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
473 const char *theme = elm_theme_get(NULL);
476 LogInfo("theme is " << m_theme);
479 // Ewk download callback (WKContextDownloadClient)
480 ewk_context_did_start_download_callback_set(
482 didStartDownloadCallback,
485 ewk_context_vibration_client_callbacks_set(
487 vibrationVibrateCallback,
488 vibrationCancelCallback,
491 ewk_context_certificate_file_set(m_ewkContext,
492 "/opt/usr/share/certs/ca-certificate.crt");
494 // set to member value
495 m_ewkContext = newEwkContext;
498 void ViewLogic::finalizeEwkContext()
500 LogInfo("finalizeEwkContext called");
501 ewk_context_message_from_injected_bundle_callback_set(
505 ewk_context_did_start_download_callback_set(
509 ewk_context_vibration_client_callbacks_set(
514 // ewk_context_delete(m_ewkContext);
518 void ViewLogic::initializeSupport()
520 // background support
521 if( m_model->SettingList.Get().getBackgroundSupport()
522 == BackgroundSupport_Enable ) {
523 LogDebug("Background support enabled, set process active");
524 pid_t pid = getpid();
525 sysman_inform_active(pid);
526 m_isBackgroundSupport = true;
528 #ifndef DEPRECATED_SETTING_STRING
530 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
531 WrtDB::PropertyDAOReadOnly::WidgetPropertyValue bgEnableValue =
532 dao.getPropertyValue(DPL::String(BACKGROUND_ENABLED));
534 if(!bgEnableValue.IsNull() && !bgEnableValue->compare(L"true")) {
536 LogDebug("Background support enabled, set process active");
537 pid_t pid = getpid();
538 sysman_inform_active(pid);
539 m_isBackgroundSupport = true;
544 // set local stroage database path
545 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
546 ewk_context_web_storage_path_set(m_ewkContext,
547 dao.getPrivateLocalStoragePath().c_str());
548 // memory saving mode
551 WrtDB::VconfConfig::GetVconfKeyMemorySavingMode(
552 m_model->TizenId).c_str(),
554 ewk_context_memory_saving_mode_set(
556 static_cast<WrtDB::SettingsType>(result) ==
557 WrtDB::SETTINGS_TYPE_ON ? EINA_TRUE : EINA_FALSE);
558 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
559 ViewModule::StorageSupport::initializeStorage(m_model);
560 m_appsSupport->initialize(m_model);
561 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
563 m_vibrationSupport->initialize();
566 void ViewLogic::initializePluginLoading()
568 // inform wrt information for plugin loading to web process
569 PluginModuleSupport::start(
572 elm_config_scale_get(),
573 ApplicationDataSingleton::Instance().getEncodedBundle(),
575 m_model->SettingList.Get().isEncrypted());
578 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
579 Assert(NULL != wkView && "ewk_view not created at this point");
581 FOREACH(it, m_ewkCallbacksMap) {
582 evas_object_smart_callback_add(
588 // EWK Orientation Callback
589 ewk_view_orientation_lock_callback_set(
591 orientationLockCallback,
595 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
596 LogDebug("ewkClientDeinit");
597 Assert(NULL != wkView && "ewk_view not created at this point");
599 FOREACH(it, m_ewkCallbacksMap) {
600 evas_object_smart_callback_del(
605 ewk_view_orientation_lock_callback_set(
611 bool ViewLogic::createEwkView(Evas* canvas)
613 LogDebug("createEwkVeiw");
615 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
616 Evas_Object* newEwkView = ewk_view_add_with_context(
619 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
622 LogError("View creation failed");
623 Wrt::Popup::PopupInvoker().showInfo(
624 "Info", "View creation failed","close");
629 // even arguments pass the ewkContext, this API should be called
630 // after webkit Evas_Object is created
631 Ewk_Cookie_Manager *ewkCookieManager;
633 ewk_context_cookie_manager_get(m_ewkContext);
634 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
635 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
637 LogInfo("push webview: " << newEwkView);
638 m_ewkViewList.push_back(newEwkView);
639 m_currentEwkView = newEwkView;
643 void ViewLogic::setStartPage()
645 /* Start URI (as other uris) is now localized
646 * on WebProcess side */
647 m_currentUri = m_startUrl;
650 void ViewLogic::prepareEwkView(Evas_Object *wkView)
652 LogDebug("prepareEwkView called");
654 Ewk_Settings* settings = ewk_view_settings_get(wkView);
657 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
658 if (customUserAgent.empty()) {
659 auto userAgentString =
660 ViewModule::UserAgentSupport::getUserAgentFromVconf();
661 if (!userAgentString.empty()) {
662 LogDebug("Setting user agent as: " << userAgentString);
663 ewk_view_user_agent_set(wkView, userAgentString.c_str());
666 LogDebug("Setting custom user agent as: " << customUserAgent);
667 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
670 // set custom header : language
671 using namespace ViewModule::CustomHeaderSupport;
672 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
673 if (!customHeaderString.empty()) {
674 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
675 LogDebug("custom value=[" << customHeaderString << "]");
676 ewk_view_custom_header_add(wkView,
677 ACCEPT_LANGUAGE.c_str(),
678 customHeaderString.c_str());
681 // webkit NPAPI plugins is always on in wrt
682 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
684 // The followings are not implemeted yet by webkit2
685 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
686 // ewk_view_mode_set();
687 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
688 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
689 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
690 // elm_webview_show_magnifier_set(EINA_FALSE);
691 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
692 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
693 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
695 // disable zoom option when user click the input field
696 // this option is useful with the normal website
697 // for the make user friendly, disable auto zoom in the webapp
698 // The followings are not implemeted yet by webkit2
699 // elm_webview_input_field_zoom_set(EINA_FALSE);
701 // set cookie database path
702 // The followings are not implemeted yet by webkit2
703 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
705 // set visibility to WebCore. This value will be used for html5.
706 // also, this value will be changed in the suspend, resume
707 // or create window, close window.
708 ewk_view_page_visibility_state_set(wkView,
709 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
713 void ViewLogic::removeEwkView(Evas_Object *wkView)
715 LogInfo("removeEwkView called");
717 Assert(0 != m_ewkViewList.size());
719 // unregister webview callbacks
720 ewkClientDeinit(wkView);
722 // suspend NPAPI plugin - Not implemented by Webkit2
723 // ewk_view_pause_or_resume_plugins();
724 evas_object_del(wkView);
725 m_ewkViewList.remove(wkView);
728 void ViewLogic::resumeEwkView(Evas_Object *wkView)
730 LogInfo("resumeEwkView called");
733 // register webview callback
734 ewkClientInit(wkView);
737 resumeWebkit(wkView);
742 void ViewLogic::suspendEwkView(Evas_Object *wkView)
744 LogInfo("suspendEwkView called");
748 suspendWebkit(wkView);
750 // unregister webview callbacks
751 ewkClientDeinit(wkView);
756 void ViewLogic::setEwkViewInvisible(Evas_Object *wkView)
758 LogInfo("setEwkViewInvisible called");
761 ewk_view_page_visibility_state_set(wkView,
762 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
764 ewk_view_visibility_set(wkView, EINA_FALSE);
767 void ViewLogic::setEwkViewVisible(Evas_Object *wkView)
769 LogInfo("setEwkViewVisible called");
772 ewk_view_page_visibility_state_set(wkView,
773 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
775 ewk_view_visibility_set(wkView, EINA_TRUE);
778 void ViewLogic::resumeWebkit(Evas_Object *wkView)
780 LogDebug("resumeWebkit");
783 // resume NPAPI plugin
784 // The followings are not implemeted yet by webkit2
785 // ewk_view_pause_or_resume_plugins(false);
786 // ewk_view_pause_or_resume_video_audio(false);
787 // ewk_view_javascript_resume();
788 // ewk_view_enable_render();
789 // ewk_view_reduce_plugins_frame_rate(false);
790 ewk_view_resume(wkView);
795 void ViewLogic::suspendWebkit(Evas_Object *wkView)
797 LogDebug("suspendWebkit");
800 // suspend the followings
801 // The followings are not implemeted yet by webkit2
802 // ewk_view_pause_or_resume_plugins(true);
803 // ewk_view_pause_or_resume_video_audio(true);
804 ewk_view_suspend(wkView);
809 void ViewLogic::contextMessageFromInjectedBundleCallback(
815 LogDebug("contextMessageFromInjectedBundleCallback called");
817 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
818 // didRecieveMessageFromInjectedBundleCallback - returnData is null
819 // didReceiveSynchronousMessageCallback - returnData isn't null
820 // WKContextInjectedBundleClient bundleClient = {
821 // kWKContextInjectedBundleClientCurrentVersion,
822 // static_cast<void*>(this),
823 // &didRecieveMessageFromInjectedBundleCallback,
824 // &didReceiveSynchronousMessageCallback
826 if (NULL == returnData) {
827 This->didRecieveMessageFromInjectedBundle(name, body);
829 This->didReceiveSynchronousMessage(name, body, returnData);
833 void ViewLogic::didStartDownloadCallback(
834 const char* downloadUrl,
837 LogDebug("didStartDownloadCallback called");
839 ViewLogic* This = static_cast<ViewLogic*>(data);
841 LogDebug("download url = " << downloadUrl);
842 This->m_appsSupport->downloadRequest(
848 void ViewLogic::loadStartedCallback(
853 LogDebug("loadStartedCallback called");
855 ViewLogic* This = static_cast<ViewLogic*>(data);
856 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
858 // call loadFinish callback to wrt-client
859 if (!This->m_cbs->loadStart.empty()) {
860 This->m_cbs->loadStart(obj);
865 void ViewLogic::loadFinishedCallback(
870 LogDebug("loadFinishedCallback called");
872 ViewLogic* This = static_cast<ViewLogic*>(data);
875 const char* url = ewk_view_url_get(This->m_currentEwkView);
876 if (NULL == url || strlen(url) == 0) {
877 LogError("url is empty");
879 DPL::OptionalString jsOptionalString =
880 ViewModule::PasswordSupport::jsForAutoFillData(url);
881 if (jsOptionalString.IsNull()) {
882 LogError("Fail to get JS String");
884 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
886 if(EINA_FALSE == ewk_view_script_execute(
887 This->m_currentEwkView,
889 didRunJavaScriptCallback,
892 LogError("JS for auto fill data failed.");
897 // call loadFinish callback to wrt-client
898 if (!This->m_cbs->loadFinish.empty()) {
899 This->m_cbs->loadFinish(obj);
902 // set only encoded bundle
903 double scale = elm_config_scale_get();
904 PluginModuleSupport::setCustomProperties(
907 ApplicationDataSingleton::Instance().getEncodedBundle());
908 // check if 'appsevice' event is registed at the current frames.
909 // If so, dispatch the event to frames.
910 PluginModuleSupport::dispatchJavaScriptEvent(
912 WrtPlugins::W3C::ServiceCustomEvent,
915 // In this case, widget is reloaded in the background.
916 // After finished load, bundle should disconnent callback.
917 if (This->m_isBackgroundReload) {
918 PluginModuleSupport::suspend(This->m_ewkContext);
919 ewk_view_suspend(This->m_currentEwkView);
920 This->m_isBackgroundReload = false;
924 void ViewLogic::titleChangedCallback(
926 Evas_Object* /*obj*/,
929 LogDebug("titleChangedCallback called");
931 ViewLogic* This = static_cast<ViewLogic*>(data);
933 const char* title = static_cast<char*>(eventInfo);
935 if (0 == strlen(title)) {
936 LogDebug("title data is empty");
939 LogDebug("Title = [" << title << "]");
940 This->m_schemeSupport->HandleTizenScheme(title,
942 This->m_currentEwkView);
945 void ViewLogic::loadProgressCallback(
947 Evas_Object* /*obj*/,
950 double* progress = static_cast<double*>(eventInfo);
951 LogDebug("didChangeProgressCallback progress = " << *progress);
954 void ViewLogic::loadProgressFinishedCallback(
956 Evas_Object* /*obj*/,
959 LogDebug("didFinishProgressCallback");
961 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
962 if (!view->m_cbs->progressFinish.empty()) {
963 view->m_cbs->progressFinish();
967 void ViewLogic::processCrashedCallback(
969 Evas_Object* /*obj*/,
972 LogInfo("processCrashedCallback");
974 ViewLogic const * const view =
975 static_cast<ViewLogic const * const>(data);
976 if (!view->m_cbs->webCrash.empty()) {
977 view->m_cbs->webCrash();
979 // This flag will be prevented exit() call in the Webkit side
980 if (NULL != eventInfo) {
981 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
985 void ViewLogic::createWindowCallback(
990 LogDebug("createWindowCallback");
992 ViewLogic* This = static_cast<ViewLogic*>(data);
994 // First, current webview should be handled by user callback
995 if (!This->m_cbs->bufferUnset.empty()) {
996 This->m_cbs->bufferUnset(obj);
999 // this can be set by executable for specific purpose
1000 Evas* canvas = NULL;
1001 if (!This->m_cbs->windowCreateBefore.empty()) {
1002 // 'obj' is parent webview object
1003 This->m_cbs->windowCreateBefore(&canvas, obj);
1006 canvas = evas_object_evas_get(This->m_window);
1009 // create new ewkview
1010 This->createEwkView(canvas);
1011 Evas_Object* newEwkView = This->m_currentEwkView;
1013 // initialize new ewkview
1014 This->setStartPage();
1015 This->ewkClientInit(newEwkView);
1016 This->prepareEwkView(newEwkView);
1018 // Specific jobs of child, parent webview are handled by each executable
1019 if (!This->m_cbs->windowCreateAfter.empty()) {
1020 // 'obj' is parent webview, 'newEwkView' is child webview
1021 This->m_cbs->windowCreateAfter(obj, newEwkView);
1024 // Lastly, new webview should be handled by user callback
1025 if (!This->m_cbs->bufferSet.empty()) {
1026 This->m_cbs->bufferSet(newEwkView);
1028 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1031 void ViewLogic::closeWindowCallback(
1034 void* /*eventInfo*/)
1036 LogDebug("closeWindowCallback");
1037 ViewLogic* This = static_cast<ViewLogic*>(data);
1038 This->m_closedEwkView = obj;
1039 ecore_idler_add(windowCloseIdlerCallback, This);
1042 void ViewLogic::policyNavigationDecideCallback(
1044 Evas_Object* /*obj*/,
1047 LogDebug("policyNavigationDecideCallback called");
1049 ViewLogic* This = static_cast<ViewLogic*>(data);
1051 Ewk_Policy_Decision* policyDecision =
1052 static_cast<Ewk_Policy_Decision*>(eventInfo);
1054 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1058 This->m_currentEwkView))
1061 ewk_policy_decision_use(policyDecision);
1063 // check whether this is new empty window
1064 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1065 if(!activeUrl || 0 == strlen(activeUrl)) {
1067 * The view is empty and scheme has been handled externally. When
1068 * user gets back from the external application he'd see blank page
1069 * and won't be able to navigate back. This happens when window.open
1070 * is used to handle schemes like sms/mms/mailto (for example in
1071 * WAC web standards tests: WS-15XX).
1073 * To solve the problem, the empty view is removed from the stack
1074 * and the previous one is shown. This is not an elegant solution
1075 * but we don't have a better one.
1077 LogInfo("Scheme has been handled externally. Removing empty view.");
1078 if (ewk_view_back_possible(This->m_currentEwkView)) {
1079 // go back to previous WKPage
1080 ewk_view_back(This->m_currentEwkView);
1082 // stop current WKPage
1083 ewk_view_stop(This->m_currentEwkView);
1084 ecore_idler_add(windowCloseIdlerCallback, This);
1089 ewk_policy_decision_ignore(policyDecision);
1093 void ViewLogic::policyNewWindowDecideCallback(
1095 Evas_Object* /*obj*/,
1098 LogDebug("policyNewWindowDecideCallback called");
1100 ViewLogic* This = static_cast<ViewLogic*>(data);
1102 Ewk_Policy_Decision* policyDecision =
1103 static_cast<Ewk_Policy_Decision*>(eventInfo);
1105 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1109 This->m_currentEwkView))
1111 ewk_policy_decision_use(policyDecision);
1114 ewk_policy_decision_ignore(policyDecision);
1118 void ViewLogic::pageResponseDecideCallback(
1120 Evas_Object* /*obj*/,
1123 LogDebug("pageResponseDecideCallback called");
1125 ViewLogic* This = static_cast<ViewLogic*>(data);
1127 Ewk_Policy_Decision* policyDecision =
1128 static_cast<Ewk_Policy_Decision*>(eventInfo);
1129 Ewk_Policy_Decision_Type policyDecisionType =
1130 ewk_policy_decision_type_get(policyDecision);
1132 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1134 ewk_policy_decision_use(policyDecision);
1135 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1136 LogDebug("download");
1137 ewk_policy_decision_suspend(policyDecision);
1139 // get uri information
1140 const char* url = ewk_policy_decision_url_get(policyDecision);
1141 if (NULL == url || strlen(url) == 0) {
1142 LogDebug("url data is empty");
1143 ewk_policy_decision_use(policyDecision);
1146 LogDebug("url = [" << url << "]");
1148 // get content information
1149 const char* content =
1150 ewk_policy_decision_response_mime_get(policyDecision);
1151 LogDebug("content type = [" << content << "]");
1153 // get cookie information
1154 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1155 LogDebug("cookie = [" << cookie << "]");
1157 LogDebug("Content not supported, will be opened in external app");
1158 This->m_appsSupport->downloadRequest(
1162 ewk_policy_decision_ignore(policyDecision);
1163 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1165 ewk_policy_decision_ignore(policyDecision);
1167 LogDebug("Type isn't handled");
1168 ewk_policy_decision_ignore(policyDecision);
1172 void ViewLogic::contextmenuCustomizeCallback(
1174 Evas_Object* /*obj*/,
1177 LogDebug("contextmenuCustomizeCallback called");
1180 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1181 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1182 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1183 (This->m_model->SettingList.Get().getContextMenu()
1184 == ContextMenu_Disable))
1186 LogDebug("ContextMenu Disable!!");
1187 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1188 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1190 ewk_context_menu_item_remove(menu, item);
1193 LogDebug("ContextMenu Enable!!");
1194 int menu_num = ewk_context_menu_item_count(menu);
1195 unsigned int idx = 0;
1197 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1202 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1205 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1206 ewk_context_menu_item_remove(menu, item);
1209 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
1210 ewk_context_menu_item_remove(menu, item);
1213 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
1214 ewk_context_menu_item_remove(menu, item);
1217 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_MEDIA_IN_NEW_WINDOW:
1218 ewk_context_menu_item_remove(menu, item);
1221 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1222 ewk_context_menu_item_remove(menu, item);
1229 } while (idx < menu_num);
1233 void ViewLogic::formSubmitCallback(
1235 Evas_Object* /*obj*/,
1238 LogDebug("formSubmitCallback called");
1240 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1242 const char* uri = ewk_form_data_url_get(formData);
1244 LogError("URL is empty");
1248 Eina_Hash* userData = ewk_form_data_values_get(formData);
1249 ViewModule::PasswordSupport::submitClicked(uri, userData);
1252 void ViewLogic::geolocationPermissionRequestCallback(
1254 Evas_Object* /*obj*/,
1258 ViewLogic* This = static_cast<ViewLogic*>(data);
1260 Ewk_Geolocation_Permission_Data* permissionRequest =
1261 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1263 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1264 SecurityOriginDB::FEATURE_GEOLOCATION)
1265 == WrtDB::SETTINGS_TYPE_OFF)
1267 ewk_geolocation_permission_request_allow_set(
1268 ewk_geolocation_permission_request_get(permissionRequest),
1272 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1274 This->m_securityOriginSupport->getSecurityOriginDAO(),
1278 void ViewLogic::notificationShowCallback(
1280 Evas_Object* /*obj*/,
1283 LogDebug("notificationShowCallback called");
1285 ViewLogic* This = static_cast<ViewLogic*>(data);
1288 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1290 using namespace ViewModule::WebNotification;
1292 WebNotificationDataPtr notiData(
1293 new WebNotificationData(
1295 ewk_notification_id_get(noti)));
1297 DPL::OptionalString string =
1298 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1299 if (!string.IsNull()) {
1300 notiData->m_iconURL = DPL::ToUTF8String(*string);
1302 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1303 if (!string.IsNull()) {
1304 notiData->m_title = DPL::ToUTF8String(*string);
1306 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1307 if (!string.IsNull()) {
1308 notiData->m_body = DPL::ToUTF8String(*string);
1311 LogInfo("notification id : " << notiData->m_id);
1312 LogInfo("notification iconURL : " << notiData->m_iconURL);
1313 LogInfo("notification title : " << notiData->m_title);
1314 LogInfo("notification body : " << notiData->m_body);
1316 showWebNotification(notiData);
1317 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1320 void ViewLogic::notificationCancelCallback(
1322 Evas_Object* /*obj*/,
1323 void* /*eventInfo*/)
1325 LogDebug("notificationCancelCallback called");
1328 void ViewLogic::notificationPermissionRequestCallback(
1330 Evas_Object* /*obj*/,
1333 LogDebug("notificationPermissionRequestCallback called");
1335 ViewLogic* This = static_cast<ViewLogic*>(data);
1336 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1337 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1338 == WrtDB::SETTINGS_TYPE_OFF)
1340 Ewk_Notification_Permission_Request* request =
1341 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1342 ewk_notification_permission_request_response(
1350 ViewModule::WebNotification::webNotificationPermissionRequest(
1352 This->m_securityOriginSupport->getSecurityOriginDAO(),
1358 void ViewLogic::vibrationVibrateCallback(uint64_t time, void* data)
1360 LogDebug("vibrationVibrateCallback called");
1362 ViewLogic* This = static_cast<ViewLogic*>(data);
1363 This->m_vibrationSupport->startVibration(static_cast<long>(time));
1367 void ViewLogic::vibrationCancelCallback(void* data)
1369 LogDebug("vibrationCancelCallback called");
1371 ViewLogic* This = static_cast<ViewLogic*>(data);
1373 This->m_vibrationSupport->stopVibration();
1378 // EWK Orientation Callback
1379 Eina_Bool ViewLogic::orientationLockCallback(
1381 Eina_Bool /*needLock*/,
1385 LogDebug("orientationLockCallback called");
1387 ViewLogic* This = static_cast<ViewLogic*>(data);
1389 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1390 LogDebug("orientation is portrait-primary");
1391 elm_win_rotation_with_resize_set(This->m_window, 0);
1392 ewk_view_orientation_send(obj, 0);
1393 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1394 LogDebug("orientation is landscape-primary");
1395 elm_win_rotation_with_resize_set(This->m_window, 270);
1396 ewk_view_orientation_send(obj, 90);
1397 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1398 LogDebug("orientation is portrait-secondary");
1399 elm_win_rotation_with_resize_set(This->m_window, 180);
1400 ewk_view_orientation_send(obj, 180);
1401 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1402 LogDebug("orientation is landscape-secondary");
1403 elm_win_rotation_with_resize_set(This->m_window, 90);
1404 ewk_view_orientation_send(obj, -90);
1406 LogDebug("Wrong orientation is set");
1413 // Fullscreen API callbacks
1414 void ViewLogic::enterFullscreenCallback(
1416 Evas_Object* /*obj*/,
1417 void* /*eventInfo*/)
1419 LogInfo("enterFullscreenCallback called");
1421 ViewLogic* This = static_cast<ViewLogic*>(data);
1422 if (!This->m_cbs->toggleFullscreen.empty()) {
1423 This->m_cbs->toggleFullscreen(true);
1426 void ViewLogic::exitFullscreenCallback(
1428 Evas_Object* /*obj*/,
1429 void* /*eventInfo*/)
1431 LogInfo("exitFullscreenCallback called");
1433 ViewLogic* This = static_cast<ViewLogic*>(data);
1434 if (!This->m_cbs->toggleFullscreen.empty()) {
1435 This->m_cbs->toggleFullscreen(false);
1439 void ViewLogic::imeChangedCallback(
1441 Evas_Object* /*obj*/,
1447 ViewLogic* This = static_cast<ViewLogic*>(data);
1448 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1449 This->m_imeWidth = rect->w;
1450 This->m_imeHeight = rect->h;
1453 void ViewLogic::imeOpenedCallback(
1455 Evas_Object* /*obj*/,
1456 void* /*eventInfo*/)
1460 ViewLogic* This = static_cast<ViewLogic*>(data);
1462 using namespace WrtPlugins::W3C;
1463 SoftKeyboardChangeArgs args;
1464 args.state = IME_STATE_ON;
1465 args.width = This->m_imeWidth;
1466 args.height = This->m_imeHeight;
1467 This->fireJavascriptEvent(
1468 static_cast<int>(SoftKeyboardChangeCustomEvent),
1472 void ViewLogic::imeClosedCallback(
1474 Evas_Object* /*obj*/,
1475 void* /*eventInfo*/)
1479 ViewLogic* This = static_cast<ViewLogic*>(data);
1481 using namespace WrtPlugins::W3C;
1482 SoftKeyboardChangeArgs args;
1483 args.state = IME_STATE_OFF;
1485 This->fireJavascriptEvent(
1486 static_cast<int>(SoftKeyboardChangeCustomEvent),
1490 void ViewLogic::usermediaPermissionRequestCallback(
1492 Evas_Object* /*obj*/,
1495 LogDebug("usermediaPermissionRequestCallback called");
1497 ViewLogic* This = static_cast<ViewLogic*>(data);
1498 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1504 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1507 Ewk_Custom_Handlers_Data* handler =
1508 static_cast<Ewk_Custom_Handlers_Data*>(data);
1509 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1510 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1512 LogDebug("base url: " << base_url);
1513 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1515 const char* url = ewk_custom_handlers_data_url_get(handler);
1517 LogDebug("url: " << url);
1518 customHandler->url = DPL::FromASCIIString(string(url));
1520 const char* target = ewk_custom_handlers_data_target_get(handler);
1522 LogDebug("target: " << target);
1523 customHandler->target = DPL::FromASCIIString(string(target));
1525 const char* title = ewk_custom_handlers_data_title_get(handler);
1527 LogDebug("title: " << title);
1528 customHandler->title = DPL::FromASCIIString(string(title));
1530 return customHandler;
1533 void ViewLogic::attachToCustomHandlersDao()
1535 if (!m_attachedToCustomHandlerDao) {
1536 CustomHandlerDB::Interface::attachDatabaseRW();
1540 void ViewLogic::detachFromCustomHandlersDao()
1542 if (m_attachedToCustomHandlerDao) {
1543 CustomHandlerDB::Interface::detachDatabase();
1547 const int protocolWhiteListLenth = 15;
1548 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1566 const int contentBlackListLenth = 14;
1567 char const * const contentBlackList[contentBlackListLenth] = {
1568 "application/x-www-form-urlencoded",
1569 "application/xhtml+xml",
1575 "multipart/x-mixed-replace",
1576 "text/cache-manifest",
1585 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1588 * @param customHandler
1590 void saveUserResponse(Wrt::Popup::PopupResponse response,
1591 CustomHandlerDB::CustomHandlerPtr customHandler)
1594 case Wrt::Popup::YES_DO_REMEMBER:
1595 LogDebug("User allowed, remember");
1596 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1597 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1599 case Wrt::Popup::YES_DONT_REMEMBER:
1600 LogDebug("User allowed, don't remember");
1601 customHandler->user_decision = CustomHandlerDB::Agreed;
1603 case Wrt::Popup::NO_DO_REMEMBER:
1604 LogDebug("User didn't allow, remember");
1605 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1606 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1608 case Wrt::Popup::NO_DONT_REMEMBER:
1609 LogDebug("User didn't allow, don't remember");
1610 customHandler->user_decision = CustomHandlerDB::Declined;
1615 //TODO registration, checking if registered and unregistration can be done in
1616 //common functions for both types of handlers. Only white and black lists
1617 //have to be separated
1618 //TODO attach database only one at the start (not in every callback?)
1619 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1625 CustomHandlerDB::CustomHandlerPtr customHandler =
1626 getCustomHandlerFromData(eventInfo);
1628 std::string scheme = DPL::ToUTF8String(customHandler->target);
1629 if (scheme.empty()) {
1630 LogError("No scheme provided");
1631 //TODO what about securityError?
1634 bool matched = false;
1635 //scheme on whiteList
1636 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1637 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1639 LogDebug("Match found, protocol can be handled");
1644 //starts with web+ and have at least 5 chars (lowercase ASCII)
1645 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1646 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1647 //throw SecurityException
1654 if (c < 'a' || c > 'z') {
1655 LogWarning("Wrong char inside scheme. "
1656 << "Only lowercase ASCII letters accepted");
1657 //throw SecurityException
1664 ViewLogic* This = static_cast<ViewLogic*>(data);
1665 LogDebug("Creating handlers dao");
1666 This->attachToCustomHandlersDao();
1667 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1668 CustomHandlerDB::CustomHandlerPtr handler =
1669 handlersDao.getProtocolHandler(customHandler->target,
1671 customHandler->base_url);
1672 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1673 LogDebug("Protocol already registered - nothing to do");
1675 LogDebug("Protocol handler not found");
1676 Wrt::Popup::PopupResponse response =
1677 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1678 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1679 PROTOCOL_HANDLER_ASK_TITLE,
1680 PROTOCOL_HANDLER_ASK_MSG,
1681 PROTOCOL_HANDLER_ASK_REMEMBER);
1682 saveUserResponse(response, customHandler);
1683 if (customHandler->user_decision == CustomHandlerDB::Declined)
1685 handlersDao.registerProtocolHandler(*(customHandler.get()));
1686 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1687 //TODO remove old default handler somehow from appsvc
1688 LogDebug("Registering appservice entry");
1689 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1691 DPL::ToUTF8String(customHandler->target).c_str(),
1692 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1693 if (APPSVC_RET_OK != ret)
1695 LogWarning("Appsvc entry failed: " << ret);
1698 LogDebug("Protocal saved");
1701 This->detachFromCustomHandlersDao();
1704 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1709 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1710 ViewLogic* This = static_cast<ViewLogic*>(data);
1711 LogDebug("Creating handlers dao");
1712 This->attachToCustomHandlersDao();
1713 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1714 CustomHandlerDB::CustomHandlerPtr handler =
1715 handlersDao.getProtocolHandler(customHandler->target,
1717 customHandler->base_url);
1719 if (handler->user_decision & CustomHandlerDB::Agreed)
1720 ewk_custom_handlers_data_result_set(
1721 static_cast<Ewk_Custom_Handlers_Data*>(data),
1722 EWK_CUSTOM_HANDLERS_REGISTERED);
1724 ewk_custom_handlers_data_result_set(
1725 static_cast<Ewk_Custom_Handlers_Data*>(data),
1726 EWK_CUSTOM_HANDLERS_DECLINED);
1728 ewk_custom_handlers_data_result_set(
1729 static_cast<Ewk_Custom_Handlers_Data*>(data),
1730 EWK_CUSTOM_HANDLERS_NEW);
1731 This->detachFromCustomHandlersDao();
1734 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1739 CustomHandlerDB::CustomHandlerPtr customHandler =
1740 getCustomHandlerFromData(eventInfo);
1741 ViewLogic* This = static_cast<ViewLogic*>(data);
1742 LogDebug("Creating handlers dao");
1743 This->attachToCustomHandlersDao();
1744 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1745 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1746 handlersDao.getProtocolHandler(customHandler->target,
1748 customHandler->base_url);
1750 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1751 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1753 handlersDao.unregisterProtocolHandler(customHandler->target,
1755 customHandler->base_url);
1757 LogDebug("Nothing to unregister");
1759 This->detachFromCustomHandlersDao();
1762 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1768 CustomHandlerDB::CustomHandlerPtr customHandler =
1769 getCustomHandlerFromData(eventInfo);
1771 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1772 if (mimeType.empty()) {
1773 LogError("No mimeType provided.");
1776 for (int i = 0; i < contentBlackListLenth; ++i)
1778 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1780 LogWarning("mimeType blacklisted");
1781 //throw SecurityException
1786 ViewLogic* This = static_cast<ViewLogic*>(data);
1787 LogDebug("Creating handlers dao");
1788 This->attachToCustomHandlersDao();
1789 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1790 CustomHandlerDB::CustomHandlerPtr handler =
1791 handlersDao.getContentHandler(customHandler->target,
1793 customHandler->base_url);
1794 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1795 LogDebug("Protocol already registered - nothing to do");
1797 LogDebug("Protocol handler not found");
1798 Wrt::Popup::PopupResponse response =
1799 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1800 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1801 CONTENT_HANDLER_ASK_TITLE,
1802 CONTENT_HANDLER_ASK_MSG,
1803 CONTENT_HANDLER_AKS_REMEMBER);
1804 saveUserResponse(response, customHandler);
1805 if (customHandler->user_decision == CustomHandlerDB::Declined)
1807 handlersDao.registerContentHandler(*(customHandler.get()));
1808 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1809 //TODO remove old default handler somehow from appsvc
1810 LogDebug("Registering appservice entry");
1811 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1812 DPL::ToUTF8String(customHandler->target).c_str(),
1814 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1815 if (APPSVC_RET_OK != ret)
1817 LogWarning("Appsvc entry failed: " << ret);
1820 LogDebug("Content saved");
1822 This->detachFromCustomHandlersDao();
1825 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1830 CustomHandlerDB::CustomHandlerPtr customHandler =
1831 getCustomHandlerFromData(eventInfo);
1832 ViewLogic* This = static_cast<ViewLogic*>(data);
1833 LogDebug("Creating handlers dao");
1835 This->attachToCustomHandlersDao();
1836 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1837 CustomHandlerDB::CustomHandlerPtr handler =
1838 handlersDao.getContentHandler(customHandler->target,
1840 customHandler->base_url);
1842 if (handler->user_decision & CustomHandlerDB::Agreed)
1843 ewk_custom_handlers_data_result_set(
1844 static_cast<Ewk_Custom_Handlers_Data*>(data),
1845 EWK_CUSTOM_HANDLERS_REGISTERED);
1847 ewk_custom_handlers_data_result_set(
1848 static_cast<Ewk_Custom_Handlers_Data*>(data),
1849 EWK_CUSTOM_HANDLERS_DECLINED);
1851 ewk_custom_handlers_data_result_set(
1852 static_cast<Ewk_Custom_Handlers_Data*>(data),
1853 EWK_CUSTOM_HANDLERS_NEW);
1854 This->detachFromCustomHandlersDao();
1857 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1862 CustomHandlerDB::CustomHandlerPtr customHandler =
1863 getCustomHandlerFromData(eventInfo);
1864 ViewLogic* This = static_cast<ViewLogic*>(data);
1865 LogDebug("Creating handlers dao");
1866 This->attachToCustomHandlersDao();
1867 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1868 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1869 handlersDao.getContentHandler(customHandler->target,
1871 customHandler->base_url);
1873 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1874 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1876 handlersDao.unregisterContentHandler(customHandler->target,
1878 customHandler->base_url);
1880 LogDebug("Nothing to unregister");
1881 This->detachFromCustomHandlersDao();
1884 void ViewLogic::didRunJavaScriptCallback(
1885 Evas_Object* /*obj*/,
1889 LogInfo("didRunJavaScriptCallback called");
1890 LogInfo("result = " << result);
1893 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1895 LogDebug("closeIdlerCallback");
1896 ViewLogic* This = static_cast<ViewLogic*>(data);
1897 This->windowClose();
1898 return ECORE_CALLBACK_CANCEL;
1901 int ViewLogic::appcoreLowMemoryCallback(void *data)
1903 LogInfo("appcoreLowMemoryCallback");
1905 ViewLogic* This = static_cast<ViewLogic*>(data);
1907 if (NULL == This->m_ewkContext) {
1908 LogInfo("ewk isn't initialize at this moment");
1910 // Crash may occur on specific situation
1911 // So use the followings after they become stable
1912 //ewk_context_cache_clear(This->m_ewkContext);
1913 //ewk_context_notify_low_memory(This->m_ewkContext);
1919 void ViewLogic::databaseUsagePermissionRequestCallback(
1921 Evas_Object* /*obj*/,
1924 LogDebug("databaseUsagePermissionRequestCallback called");
1926 ViewLogic* This = static_cast<ViewLogic*>(data);
1929 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1930 SecurityOriginDB::FEATURE_WEB_DATABASE)
1931 == WrtDB::SETTINGS_TYPE_OFF)
1933 // default value is deny
1936 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1938 This->m_securityOriginSupport->getSecurityOriginDAO(),
1943 void ViewLogic::fileSystemPermissionRequestCallback(
1945 Evas_Object* /*obj*/,
1948 LogDebug("fileSystemPermissionRequestCallback called");
1950 ViewLogic* This = static_cast<ViewLogic*>(data);
1952 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1953 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
1954 == WrtDB::SETTINGS_TYPE_OFF)
1956 Ewk_Context_File_System_Permission* fileSystemPermission =
1957 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
1958 ewk_context_file_system_permission_allow_set(fileSystemPermission,
1964 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1966 This->m_securityOriginSupport->getSecurityOriginDAO(),
1970 void ViewLogic::certificateConfirmRequestCallback(
1972 Evas_Object* /*obj*/,
1975 LogDebug("certificateConfirmRequestCallback called");
1978 ViewLogic* This = static_cast<ViewLogic*>(data);
1980 Ewk_Certificate_Policy_Decision* certificatePolicyDecision =
1981 static_cast<Ewk_Certificate_Policy_Decision*>(eventInfo);
1983 bool status = This->askUserForCertificateConfirm();
1985 ewk_certificate_policy_decision_allowed_set(
1986 certificatePolicyDecision,
1990 ewk_certificate_policy_decision_allowed_set(
1991 certificatePolicyDecision,
1996 bool ViewLogic::askUserForCertificateConfirm()
1998 return Wrt::Popup::PopupInvoker().askYesNo(
1999 CERTIFICATE_CONFIRM_REQUEST_ASK_TITLE,
2000 CERTIFICATE_CONFIRM_REQUEST_ASK_BODY);
2003 void ViewLogic::didRecieveMessageFromInjectedBundle(
2005 const char* /*body*/)
2007 LogDebug("did recive message " << name);
2010 void ViewLogic::didReceiveSynchronousMessage(
2015 LogDebug("didReceiveSynchronousMessage called");
2020 LogDebug("body is empty");
2024 if (!strcmp(name, uriBlockedMessageName)) {
2025 LogDebug("received : " << uriBlockedMessageName);
2026 // Currently WebProcess informs obly about blocked
2027 // URI - URI localization and security chekcs are
2028 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2029 // and bundle_uri_handling.cpp)
2030 rememberBlockedURI(DPL::FromUTF8String(body));
2032 } else if (!strcmp(name, uriChangedMessageName)) {
2033 LogDebug("received : " << uriChangedMessageName);
2034 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2035 *returnData = strdup(ret.c_str());
2039 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2041 m_blockedUri = DPL::ToUTF8String(inputURI);
2042 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2046 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2048 using namespace ViewModule::SecuritySupport;
2050 std::string url = DPL::ToUTF8String(changedURL);
2051 LogInfo("URL = [" << url << "]");
2054 // If url is same to URICHANGE_BLOCKED_URL,
2055 // this url has been already blocked by willsend.
2056 // So current page should be moved to previous page
2057 if (url == URICHANGE_BLOCKED_URL)
2059 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2061 // block this page and open it in browser
2062 LogDebug("Request was blocked by WARP: " << url.c_str());
2063 if (!m_blockedUri.empty()) {
2064 LogDebug("open browser : " << m_blockedUri);
2065 bundle* bundleData = bundle_create();
2066 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2067 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2068 CONTROLLER_POST_EVENT(
2069 ApplicationLauncher,
2070 ApplicationLauncherEvents::LaunchApplicationByAppService(
2074 m_blockedUri = std::string();
2077 if (ewk_view_back_possible(m_currentEwkView)) {
2078 // go back to previous page
2079 ewk_view_back(m_currentEwkView);
2081 // stop current page
2082 ewk_view_stop(m_currentEwkView);
2083 ecore_idler_add(windowCloseIdlerCallback, this);
2086 // This is used in case of returning previous page
2088 return URICHANGE_PLUGIN_NO_CHANGE;
2093 // Check if this url with 'http' or 'https' is included in whitelist,
2094 // which has lists of accessible external documents and
2095 // used for ONLY Tizen app
2096 std::string matchedScheme;
2097 std::string matchedUri;
2098 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2101 ViewModule::Scheme scheme(matchedScheme);
2102 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2103 scheme.GetType() == ViewModule::Scheme::HTTPS)
2105 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2106 if (!checkWhitelist(url.c_str())) {
2107 LogInfo("This uri is not included in white document list");
2108 return URICHANGE_PLUGIN_STOP_ONLY;
2110 LogInfo("This url is included in WhiteList");
2112 // For WAC app, WRT should block access of device api
2113 // for external documents
2114 return URICHANGE_PLUGIN_STOP_ONLY;
2118 // register javascript object for plugins to be used
2119 LogInfo("Register Plugin Objects");
2120 return URICHANGE_PLUGIN_RESTART;
2123 void ViewLogic::windowClose()
2125 LogDebug("windowClose");
2126 Assert(m_closedEwkView && "no closed webview");
2128 if (1 >= m_ewkViewList.size()) {
2129 if (!m_cbs->webkitExit.empty()) {
2130 m_cbs->webkitExit();
2133 // call user callbacks
2134 if (!m_cbs->bufferUnset.empty()) {
2135 m_cbs->bufferUnset(m_currentEwkView);
2137 if (!m_cbs->windowClose.empty()) {
2138 m_cbs->windowClose(m_closedEwkView);
2140 removeEwkView(m_closedEwkView);
2142 // get latest ewkView
2143 m_currentEwkView = m_ewkViewList.back();
2144 const char* uri = ewk_view_url_get(m_currentEwkView);
2145 if (NULL == uri || 0 == strlen(uri)) {
2146 m_currentUri.clear();
2152 /* In case we support many pages in parallel
2153 then view is not suspended*/
2154 //resumeEwkView(m_currentEwkView);
2157 if (!m_cbs->bufferSet.empty()) {
2158 m_cbs->bufferSet(m_currentEwkView);