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 <Elementary.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_certificate_support.h>
52 #include <common/view_logic_storage_support.h>
53 #include <common/view_logic_uri_support.h>
54 #include <common/view_logic_user_agent_support.h>
55 #include <common/view_logic_vibration_support.h>
56 #include <view_logic_authentication_challenge_support.h>
57 #include <view_logic_scheme_support.h>
58 #include <view_logic_geolocation_support.h>
59 #include <view_logic_usermedia_support.h>
60 #include <view_logic_web_notification_support.h>
62 #include <view_logic_certificate_confirm_support.h>
63 #include "bundles/plugin_module_support.h"
64 #include <popup-runner/PopupInvoker.h>
67 #include <dpl/localization/w3c_file_localization.h>
68 #include <js_overlay_types.h>
69 #include <i_runnable_widget_object.h>
70 #include <profiling_util.h>
71 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
72 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
73 #include <popup-runner/PopupInvoker.h>
75 #include <appsvc/appsvc.h>
78 const char * const uriBlockedMessageName = "uri_blocked_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* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
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";
96 const int WIN_ORIENTATION_PORTRAIT_PRIMARY_ANGLE = 0;
97 const int WIN_ORIENTATION_PORTRAIT_SECONDARY_ANGLE = 180;
98 const int WIN_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE = 270;
99 const int WIN_ORIENTATION_LANDSCAPE_SECONDARY_ANGLE = 90;
100 const int W3C_ORIENTATION_PORTRAIT_PRIMARY_ANGLE = 0;
101 const int W3C_ORIENTATION_PORTRAIT_SECONDARY_ANGLE = 180;
102 const int W3C_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE = 90;
103 const int W3C_ORIENTATION_LANDSCAPE_SECONDARY_ANGLE = -90;
104 } // anonymous namespace
106 std::map<const std::string,
107 const Evas_Smart_Cb> ViewLogic::m_ewkCallbacksMap = {
108 { "load,started", &ViewLogic::loadStartedCallback },
109 { "load,finished", &ViewLogic::loadFinishedCallback },
110 { "title,changed", &ViewLogic::titleChangedCallback },
111 { "load,progress", &ViewLogic::loadProgressCallback },
112 { "load,progress,finished", &ViewLogic::loadProgressFinishedCallback },
113 { "process,crashed", &ViewLogic::processCrashedCallback },
115 { "create,window", &ViewLogic::createWindowCallback },
116 { "close,window", &ViewLogic::closeWindowCallback },
117 // WKPagePolicyClient
118 { "policy,navigation,decide", &ViewLogic::policyNavigationDecideCallback },
119 { "policy,newwindow,decide", &ViewLogic::policyNewWindowDecideCallback },
120 { "policy,response,decide", &ViewLogic::pageResponseDecideCallback },
121 // WKPageContextMenuClient
122 { "contextmenu,customize", &ViewLogic::contextmenuCustomizeCallback },
124 { "form,submit", &ViewLogic::formSubmitCallback },
125 // EWK Geolocation Callback
126 { "geolocation,permission,request",
127 &ViewLogic::geolocationPermissionRequestCallback },
128 // EWK Notification Callback
129 { "notification,show", &ViewLogic::notificationShowCallback },
130 { "notification,cancel", &ViewLogic::notificationCancelCallback },
131 { "notification,permission,request",
132 &ViewLogic::notificationPermissionRequestCallback },
134 { "fullscreen,enterfullscreen", &ViewLogic::enterFullscreenCallback },
135 { "fullscreen,exitfullscreen", &ViewLogic::exitFullscreenCallback },
137 // when ime start to be showed on the webview,
138 // this callback will be called
139 { "inputmethod,changed", &ViewLogic::imeChangedCallback },
140 // this callback will be called
141 // when ime finishes to be showed on the webview
142 // "event_info" arg of this callback is always NULL point
143 // if web content should know size of ime,
144 // use "inputmethod,changed" instead of this.
146 { "editorclient,ime,opened", &ViewLogic::imeOpenedCallback },
147 // when ime finished to be hidden,
148 // this callback will be called
149 { "editorclient,ime,closed", &ViewLogic::imeClosedCallback },
150 // EWK Usermedia Callback
151 { "usermedia,permission,request",
152 &ViewLogic::usermediaPermissionRequestCallback },
154 { "protocolhandler,registration,requested",
155 &ViewLogic::protocolHandlerRegistrationCallback },
156 { "protocolhandler,isregistered",
157 &ViewLogic::protocolHandlerIsRegisteredCallback },
158 { "protocolhandler,unregistration,requested",
159 &ViewLogic::protocolHandlerUnregistrationCallback },
160 { "contenthandler,registration,requested",
161 &ViewLogic::contentHandlerRegistrationCallback },
162 { "contenthandler,isregistered",
163 &ViewLogic::contentHandlerIsRegisteredCallback },
164 { "contenthandler,unregistration,requested",
165 &ViewLogic::contentHandlerUnregistrationCallback },
166 { "request,certificate,confirm",
167 &ViewLogic::certificateConfirmRequestCallback },
168 { "authentication,challenge",
169 &ViewLogic::authenticationChallengeRequestCallback },
171 &ViewLogic::viewFrameRenderedCallback }
174 ViewLogic::ViewLogic() :
176 m_attachedToCustomHandlerDao(false),
178 m_closedEwkView(NULL),
181 m_cbs(new WRT::UserDelegates),
184 m_isBackgroundReload(false),
185 m_isBackgroundSupport(false),
186 m_appsSupport(new ViewModule::AppsSupport()),
187 m_vibrationSupport(new ViewModule::VibrationSupport())
189 ApplicationLauncherSingleton::Instance().Touch();
192 ViewLogic::~ViewLogic()
194 detachFromCustomHandlersDao();
197 bool ViewLogic::createWebView(Ewk_Context* context,
201 if (!context || !window) {
206 const char *theme = elm_theme_get(NULL);
209 LogInfo("theme is " << m_theme);
213 m_ewkContext = context;
216 Evas* canvas = evas_object_evas_get(m_window);
217 return createEwkView(canvas);
220 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
222 LogDebug("View prepare");
226 m_startUrl = startUrl;
227 Assert(NULL != m_ewkContext);
230 ADD_PROFILING_POINT("initializeSupport", "start");
232 ADD_PROFILING_POINT("initializeSupport", "stop");
234 ewkClientInit(m_currentEwkView);
235 ADD_PROFILING_POINT("prepareEwkView", "start");
236 prepareEwkView(m_currentEwkView);
237 ADD_PROFILING_POINT("prepareEwkView", "stop");
238 initializePluginLoading();
241 void ViewLogic::showWidget()
243 LogDebug("showing widget");
244 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
245 if (m_currentUri.empty()) {
246 LogError("Localized current URI doesn't exist");
250 LogInfo("m_currentUri: " << m_currentUri);
253 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
255 if (!m_cbs->bufferSet.empty()) {
256 m_cbs->bufferSet(m_currentEwkView);
260 void ViewLogic::hideWidget()
262 LogDebug("hiding widget");
263 ViewModule::StorageSupport::deinitializeStorage(m_model);
264 m_appsSupport->deinitialize();
266 m_vibrationSupport->deinitialize();
268 while (!m_ewkViewList.empty()) {
269 LogInfo("pop webview: " << m_ewkViewList.back());
270 removeEwkView(m_ewkViewList.back());
272 m_ewkViewList.clear();
275 void ViewLogic::suspendWidget()
277 LogInfo("Pausing widget");
280 if (!m_currentEwkView) {
281 LogWarning("Cannot suspend widget without view");
283 setEwkViewInvisible(m_currentEwkView);
284 if (!m_isBackgroundSupport) {
285 suspendWebkit(m_currentEwkView);
289 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
291 // call user callback
292 if (!m_cbs->suspend.empty()) {
293 m_cbs->suspend(true);
297 void ViewLogic::resumeWidget()
299 LogInfo("Resume widget");
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.empty()) {
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 m_currentUri = DPL::ToUTF8String(*servicedUri);
351 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
352 elm_win_activate(m_window);
353 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
355 // call user callback
356 if (!m_cbs->reset.empty()) {
359 if (!m_cbs->bufferSet.empty()) {
360 m_cbs->bufferSet(m_currentEwkView);
364 void ViewLogic::backward()
366 if (ewk_view_back_possible(m_currentEwkView)) {
367 ewk_view_back(m_currentEwkView);
369 if (1 >= m_ewkViewList.size()) {
370 // If there is no previous page, widget move to backgroud.
371 LogInfo("Widget move to backgroud");
372 elm_win_lower(m_window);
374 // Back to previous webview
375 LogInfo("Widget move to previous webview");
376 m_closedEwkView = m_currentEwkView;
377 ecore_idler_add(windowCloseIdlerCallback, this);
382 void ViewLogic::reloadStartPage()
384 LogInfo("Reload Start Page");
385 // prevent fail to load plugin bundle side
386 m_isBackgroundReload = true;
388 if (!m_ewkViewList.empty()) {
389 while (!m_ewkViewList.empty()) {
390 if (!m_cbs->bufferUnset.empty()) {
391 m_cbs->bufferUnset(m_currentEwkView);
393 removeEwkView(m_currentEwkView);
397 // create new webview
398 createEwkView(evas_object_evas_get(m_window));
399 ewkClientInit(m_currentEwkView);
402 prepareEwkView(m_currentEwkView);
403 initializePluginLoading();
406 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
409 if (!m_cbs->bufferSet.empty()) {
410 m_cbs->bufferSet(m_currentEwkView);
412 LogInfo("Reloading Start Page is done!");
415 Evas_Object* ViewLogic::getCurrentWebview()
417 LogInfo("get current webview");
418 return m_currentEwkView;
421 void ViewLogic::fireJavascriptEvent(int event, void* data)
423 PluginModuleSupport::dispatchJavaScriptEvent(
425 static_cast<WrtPlugins::W3C::CustomEventType>(event),
429 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
434 void ViewLogic::checkSyncMessageFromBundle(
439 LogDebug("didReceiveSynchronousMessage called");
444 LogDebug("body is empty");
449 LogDebug("received : " << name);
451 if (!strcmp(name, 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 result = requestUrlBlocked(std::string(body));
457 } else if (!strcmp(name, uriChangedMessageName)) {
458 result = requestUrlChanged(std::string(body));
461 *returnData = strdup(result.c_str());
464 void ViewLogic::downloadData(const char* url)
471 m_appsSupport->downloadRequest(url, NULL, NULL);
474 void ViewLogic::activateVibration(bool on, uint64_t time)
478 m_vibrationSupport->startVibration(static_cast<long>(time));
480 m_vibrationSupport->stopVibration();
484 void ViewLogic::initializeSupport()
486 // background support
487 if (m_model->SettingList.Get().getBackgroundSupport()
488 == BackgroundSupport_Enable)
490 LogDebug("Background support enabled, set process active");
491 pid_t pid = getpid();
492 sysman_inform_active(pid);
493 m_isBackgroundSupport = true;
495 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
496 ViewModule::StorageSupport::initializeStorage(m_model);
497 m_appsSupport->initialize(m_model);
498 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
499 m_certificateSupport.reset(new ViewModule::CertificateSupport(m_model));
501 m_vibrationSupport->initialize();
504 void ViewLogic::initializePluginLoading()
506 // inform wrt information for plugin loading to web process
507 PluginModuleSupport::start(
510 elm_config_scale_get(),
511 ApplicationDataSingleton::Instance().getEncodedBundle(),
513 m_model->SettingList.Get().isEncrypted());
516 void ViewLogic::ewkClientInit(Evas_Object *wkView)
518 Assert(NULL != wkView && "ewk_view not created at this point");
520 FOREACH(it, m_ewkCallbacksMap)
522 evas_object_smart_callback_add(
528 // EWK Orientation Callback
529 ewk_view_orientation_lock_callback_set(
531 orientationLockCallback,
535 void ViewLogic::ewkClientDeinit(Evas_Object *wkView)
537 LogDebug("ewkClientDeinit");
538 Assert(NULL != wkView && "ewk_view not created at this point");
540 FOREACH(it, m_ewkCallbacksMap)
542 evas_object_smart_callback_del(
547 ewk_view_orientation_lock_callback_set(
553 bool ViewLogic::createEwkView(Evas* canvas)
555 LogDebug("createEwkView");
557 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
558 Evas_Object* newEwkView = ewk_view_add_with_context(
561 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
564 LogError("View creation failed");
565 Wrt::Popup::PopupInvoker().showInfo(
566 "Info", "View creation failed", "close");
571 // even arguments pass the ewkContext, this API should be called
572 // after webkit Evas_Object is created
573 Ewk_Cookie_Manager *ewkCookieManager;
575 ewk_context_cookie_manager_get(m_ewkContext);
576 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
577 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
579 if (m_currentEwkView) {
580 setEwkViewInvisible(m_currentEwkView);
583 LogInfo("push webview: " << newEwkView);
584 m_ewkViewList.push_back(newEwkView);
585 m_currentEwkView = newEwkView;
589 void ViewLogic::setStartPage()
591 /* Start URI (as other uris) is now localized
592 * on WebProcess side */
593 m_currentUri = ViewModule::UriSupport::getUri(m_model, m_startUrl);
596 void ViewLogic::prepareEwkView(Evas_Object *wkView)
598 LogDebug("prepareEwkView called");
602 LogInfo("Setting CSP default policy");
603 ewk_context_tizen_extensible_api_set(
604 m_ewkContext, EWK_EXTENSIBLE_API_CSP, true);
605 // setting CSP policy rules
606 // temporary turn off
607 //ewk_view_content_security_policy_set(
609 // "default-src '*'; script-src 'self'; style-src 'self'; object-src 'none';",
610 // EWK_ENFORCE_POLICY);
611 //LogInfo("Default policy set");
613 DPL::OptionalString policy = m_model->CspReportOnlyPolicy.Get();
615 if (!(policy.IsNull()))
617 LogDebug("CSP report only policy present in manifest: " << *policy);
618 ewk_view_content_security_policy_set(
619 wkView, DPL::ToUTF8String(*policy).c_str(), EWK_REPORT_ONLY);
621 LogDebug("Config CSP report only policy is not present");
624 policy = m_model->CspPolicy.Get();
626 if (!(policy.IsNull()))
628 LogDebug("CSP policy present in manifest: " << *policy);
629 ewk_view_content_security_policy_set(
630 wkView, DPL::ToUTF8String(*policy).c_str(), EWK_ENFORCE_POLICY);
632 LogDebug("Config CSP policy is not present");
639 Ewk_Settings* settings = ewk_view_settings_get(wkView);
642 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
643 if (customUserAgent.empty()) {
644 auto userAgentString =
645 ViewModule::UserAgentSupport::getUserAgentFromVconf();
646 if (!userAgentString.empty()) {
647 LogDebug("Setting user agent as: " << userAgentString);
648 ewk_view_user_agent_set(wkView, userAgentString.c_str());
651 LogDebug("Setting custom user agent as: " << customUserAgent);
652 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
655 // set custom header : language
656 using namespace ViewModule::CustomHeaderSupport;
657 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
658 if (!customHeaderString.empty()) {
659 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
660 LogDebug("custom value=[" << customHeaderString << "]");
661 ewk_view_custom_header_add(wkView,
662 ACCEPT_LANGUAGE.c_str(),
663 customHeaderString.c_str());
666 // webkit NPAPI plugins is always on in wrt
667 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
669 // The followings are not implemeted yet by webkit2
670 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
671 // ewk_view_mode_set();
672 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE,
674 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
675 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
676 // elm_webview_show_magnifier_set(EINA_FALSE);
677 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
678 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
679 // WRT should not fit web contents to device width automatically as default.
680 // Fitting to device width should be handled by web content using viewport meta tag.
681 ewk_settings_auto_fitting_set(settings, EINA_FALSE);
683 // disable zoom option when user click the input field
684 // this option is useful with the normal website
685 // for the make user friendly, disable auto zoom in the webapp
686 // The followings are not implemeted yet by webkit2
687 // elm_webview_input_field_zoom_set(EINA_FALSE);
689 // set cookie database path
690 // The followings are not implemeted yet by webkit2
691 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
693 // set visibility to WebCore. This value will be used for html5.
694 // also, this value will be changed in the suspend, resume
695 // or create window, close window.
696 ewk_view_page_visibility_state_set(wkView,
697 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
700 std::string encoding="UTF-8";
701 OptionalWidgetStartFileInfo fileInfo = W3CFileLocalization::getStartFileInfo(m_model->TizenId);
702 if(!fileInfo.IsNull()){
703 encoding=DPL::ToUTF8String((*fileInfo).encoding);
704 LogInfo("Found custom encoding in DB: " << encoding);
706 LogInfo("Setting encoding: " << encoding);
707 if(ewk_settings_default_encoding_set(settings,encoding.c_str()))
708 LogInfo("Encoding set properly");
710 LogInfo("Error while setting encoding");
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);
755 void ViewLogic::setEwkViewInvisible(Evas_Object *wkView)
757 LogInfo("setEwkViewInvisible called");
760 ewk_view_page_visibility_state_set(wkView,
761 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
763 ewk_view_visibility_set(wkView, EINA_FALSE);
766 void ViewLogic::setEwkViewVisible(Evas_Object *wkView)
768 LogInfo("setEwkViewVisible called");
771 ewk_view_page_visibility_state_set(wkView,
772 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
774 ewk_view_visibility_set(wkView, EINA_TRUE);
777 void ViewLogic::resumeWebkit(Evas_Object *wkView)
779 LogDebug("resumeWebkit");
782 // resume NPAPI plugin
783 // The followings are not implemeted yet by webkit2
784 // ewk_view_pause_or_resume_plugins(false);
785 // ewk_view_pause_or_resume_video_audio(false);
786 // ewk_view_javascript_resume();
787 // ewk_view_enable_render();
788 // ewk_view_reduce_plugins_frame_rate(false);
789 ewk_view_resume(wkView);
794 void ViewLogic::suspendWebkit(Evas_Object *wkView)
796 LogDebug("suspendWebkit");
799 // suspend the followings
800 // The followings are not implemeted yet by webkit2
801 // ewk_view_pause_or_resume_plugins(true);
802 // ewk_view_pause_or_resume_video_audio(true);
803 ewk_view_suspend(wkView);
808 void ViewLogic::loadStartedCallback(
813 LogDebug("loadStartedCallback called");
815 ViewLogic* This = static_cast<ViewLogic*>(data);
816 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
818 // call loadFinish callback to wrt-client
819 if (!This->m_cbs->loadStart.empty()) {
820 This->m_cbs->loadStart(obj);
824 void ViewLogic::loadFinishedCallback(
829 LogDebug("loadFinishedCallback called");
831 ViewLogic* This = static_cast<ViewLogic*>(data);
834 const char* url = ewk_view_url_get(This->m_currentEwkView);
835 if (NULL == url || strlen(url) == 0) {
836 LogError("url is empty");
840 DPL::OptionalString jsOptionalString =
841 ViewModule::PasswordSupport::jsForAutoFillData(url);
842 if (jsOptionalString.IsNull()) {
843 LogError("Fail to get JS String");
845 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
847 if (EINA_FALSE == ewk_view_script_execute(
848 This->m_currentEwkView,
850 didRunJavaScriptCallback,
853 LogError("JS for auto fill data failed.");
857 // call loadFinish callback to wrt-client
858 if (!This->m_cbs->loadFinish.empty()) {
859 This->m_cbs->loadFinish(obj);
862 // set only encoded bundle
863 double scale = elm_config_scale_get();
864 PluginModuleSupport::setCustomProperties(
867 ApplicationDataSingleton::Instance().getEncodedBundle());
868 // check if 'appsevice' event is registed at the current frames.
869 // If so, dispatch the event to frames.
870 PluginModuleSupport::dispatchJavaScriptEvent(
872 WrtPlugins::W3C::ServiceCustomEvent,
875 // In this case, widget is reloaded in the background.
876 // After finished load, bundle should disconnent callback.
877 if (This->m_isBackgroundReload) {
878 ewk_view_suspend(This->m_currentEwkView);
879 This->m_isBackgroundReload = false;
883 void ViewLogic::titleChangedCallback(
888 LogDebug("titleChangedCallback called");
890 ViewLogic* This = static_cast<ViewLogic*>(data);
892 const char* title = static_cast<char*>(eventInfo);
894 if (0 == strlen(title)) {
895 LogDebug("title data is empty");
896 This->m_currentTitle = std::string();
899 LogDebug("Title = [" << title << "]");
900 bool ret = This->m_schemeSupport->HandleTizenScheme(
903 This->m_currentEwkView);
904 // if result is true, this is tizen scheme
905 // and then, title is reset to page's real title
907 std::string script = "document.title = \"";
908 script += This->m_currentTitle;
910 ewk_view_script_execute(obj, script.c_str(), didRunJavaScriptCallback, This);
912 This->m_currentTitle = std::string(title);
916 void ViewLogic::loadProgressCallback(
921 LogDebug("loadProgressCallback called");
924 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
925 double* progress = static_cast<double*>(eventInfo);
926 LogDebug("didChangeProgressCallback progress = " << *progress);
927 if (!view->m_cbs->progress.empty()) {
929 view->m_cbs->progress(obj, *progress);
933 void ViewLogic::loadProgressFinishedCallback(
935 Evas_Object* /*obj*/,
938 LogDebug("didFinishProgressCallback");
940 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
941 if (!view->m_cbs->progressFinish.empty()) {
942 view->m_cbs->progressFinish();
946 void ViewLogic::processCrashedCallback(
948 Evas_Object* /*obj*/,
951 LogInfo("processCrashedCallback");
953 ViewLogic const * const view =
954 static_cast<ViewLogic const * const>(data);
955 if (!view->m_cbs->webCrash.empty()) {
956 view->m_cbs->webCrash();
958 // This flag will be prevented exit() call in the Webkit side
959 if (NULL != eventInfo) {
960 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
964 void ViewLogic::createWindowCallback(
969 LogDebug("createWindowCallback");
971 ViewLogic* This = static_cast<ViewLogic*>(data);
973 // First, current webview should be handled by user callback
974 if (!This->m_cbs->bufferUnset.empty()) {
975 This->m_cbs->bufferUnset(obj);
978 // this can be set by executable for specific purpose
980 if (!This->m_cbs->windowCreateBefore.empty()) {
981 // 'obj' is parent webview object
982 This->m_cbs->windowCreateBefore(&canvas, obj);
985 canvas = evas_object_evas_get(This->m_window);
988 // create new ewkview
989 This->createEwkView(canvas);
990 Evas_Object* newEwkView = This->m_currentEwkView;
992 // initialize new ewkview
993 This->setStartPage();
994 This->ewkClientInit(newEwkView);
995 This->prepareEwkView(newEwkView);
997 // Specific jobs of child, parent webview are handled by each executable
998 if (!This->m_cbs->windowCreateAfter.empty()) {
999 // 'obj' is parent webview, 'newEwkView' is child webview
1000 This->m_cbs->windowCreateAfter(obj, newEwkView);
1003 // Lastly, new webview should be handled by user callback
1004 if (!This->m_cbs->bufferSet.empty()) {
1005 This->m_cbs->bufferSet(newEwkView);
1007 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1010 void ViewLogic::closeWindowCallback(
1013 void* /*eventInfo*/)
1015 LogDebug("closeWindowCallback");
1016 ViewLogic* This = static_cast<ViewLogic*>(data);
1017 This->m_closedEwkView = obj;
1018 ecore_idler_add(windowCloseIdlerCallback, This);
1021 void ViewLogic::policyNavigationDecideCallback(
1023 Evas_Object* /*obj*/,
1026 LogDebug("policyNavigationDecideCallback called");
1028 ViewLogic* This = static_cast<ViewLogic*>(data);
1030 Ewk_Policy_Decision* policyDecision =
1031 static_cast<Ewk_Policy_Decision*>(eventInfo);
1033 // handle blocked url
1034 const char* url = ewk_policy_decision_url_get(policyDecision);
1035 if (url && strlen(url) != 0) {
1036 if (This->m_blockedUri == url) {
1037 LogDebug("Blocked url = " << url);
1038 This->m_blockedUri = std::string();
1039 ewk_policy_decision_ignore(policyDecision);
1044 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1048 This->m_currentEwkView))
1051 ewk_policy_decision_use(policyDecision);
1053 // check whether this is new empty window
1054 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1055 if (!activeUrl || 0 == strlen(activeUrl)) {
1057 * The view is empty and scheme has been handled externally. When
1058 * user gets back from the external application he'd see blank page
1059 * and won't be able to navigate back. This happens when window.open
1060 * is used to handle schemes like sms/mms/mailto (for example in
1061 * WAC web standards tests: WS-15XX).
1063 * To solve the problem, the empty view is removed from the stack
1064 * and the previous one is shown. This is not an elegant solution
1065 * but we don't have a better one.
1067 LogInfo("Scheme has been handled externally. Removing empty view.");
1068 if (ewk_view_back_possible(This->m_currentEwkView)) {
1069 // go back to previous WKPage
1070 ewk_view_back(This->m_currentEwkView);
1072 // stop current WKPage
1073 ewk_view_stop(This->m_currentEwkView);
1074 This->m_closedEwkView = This->m_currentEwkView;
1075 ecore_idler_add(windowCloseIdlerCallback, This);
1080 ewk_policy_decision_ignore(policyDecision);
1084 void ViewLogic::policyNewWindowDecideCallback(
1086 Evas_Object* /*obj*/,
1089 LogDebug("policyNewWindowDecideCallback called");
1091 ViewLogic* This = static_cast<ViewLogic*>(data);
1093 Ewk_Policy_Decision* policyDecision =
1094 static_cast<Ewk_Policy_Decision*>(eventInfo);
1096 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1100 This->m_currentEwkView))
1102 ewk_policy_decision_use(policyDecision);
1105 ewk_policy_decision_ignore(policyDecision);
1109 void ViewLogic::pageResponseDecideCallback(
1111 Evas_Object* /*obj*/,
1114 LogDebug("pageResponseDecideCallback called");
1116 ViewLogic* This = static_cast<ViewLogic*>(data);
1118 Ewk_Policy_Decision* policyDecision =
1119 static_cast<Ewk_Policy_Decision*>(eventInfo);
1120 Ewk_Policy_Decision_Type policyDecisionType =
1121 ewk_policy_decision_type_get(policyDecision);
1123 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1125 ewk_policy_decision_use(policyDecision);
1126 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1127 LogDebug("download");
1128 ewk_policy_decision_suspend(policyDecision);
1130 // get uri information
1131 const char* url = ewk_policy_decision_url_get(policyDecision);
1132 if (NULL == url || strlen(url) == 0) {
1133 LogDebug("url data is empty");
1134 ewk_policy_decision_use(policyDecision);
1137 LogDebug("url = [" << url << "]");
1139 // get content information
1140 const char* content =
1141 ewk_policy_decision_response_mime_get(policyDecision);
1142 LogDebug("content type = [" << content << "]");
1144 // get cookie information
1145 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1146 LogDebug("cookie = [" << cookie << "]");
1148 LogDebug("Content not supported, will be opened in external app");
1149 This->m_appsSupport->downloadRequest(
1153 ewk_policy_decision_ignore(policyDecision);
1154 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1156 ewk_policy_decision_ignore(policyDecision);
1158 LogDebug("Type isn't handled");
1159 ewk_policy_decision_ignore(policyDecision);
1163 void ViewLogic::contextmenuCustomizeCallback(
1165 Evas_Object* /*obj*/,
1168 LogDebug("contextmenuCustomizeCallback called");
1171 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1172 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1173 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1174 (This->m_model->SettingList.Get().getContextMenu()
1175 == ContextMenu_Disable))
1177 LogDebug("ContextMenu Disable!!");
1178 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1179 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1182 ewk_context_menu_item_remove(menu, item);
1185 LogDebug("ContextMenu Enable!!");
1186 unsigned int menu_num = ewk_context_menu_item_count(menu);
1187 unsigned int idx = 0;
1189 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu,
1195 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1198 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1199 ewk_context_menu_item_remove(menu, item);
1202 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW:
1203 ewk_context_menu_item_remove(menu, item);
1206 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_FRAME_IN_NEW_WINDOW:
1207 ewk_context_menu_item_remove(menu, item);
1210 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_MEDIA_IN_NEW_WINDOW:
1211 ewk_context_menu_item_remove(menu, item);
1214 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1215 ewk_context_menu_item_remove(menu, item);
1222 } while (idx < menu_num);
1226 void ViewLogic::formSubmitCallback(
1228 Evas_Object* /*obj*/,
1231 LogDebug("formSubmitCallback called");
1233 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1235 const char* uri = ewk_form_data_url_get(formData);
1237 LogError("URL is empty");
1241 Eina_Hash* userData = ewk_form_data_values_get(formData);
1242 ViewModule::PasswordSupport::submitClicked(uri, userData);
1245 void ViewLogic::geolocationPermissionRequestCallback(
1247 Evas_Object* /*obj*/,
1251 ViewLogic* This = static_cast<ViewLogic*>(data);
1253 Ewk_Geolocation_Permission_Request* permissionRequest =
1254 static_cast<Ewk_Geolocation_Permission_Request*>(eventInfo);
1256 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1257 WrtDB::FEATURE_GEOLOCATION)
1258 == WrtDB::SETTINGS_TYPE_OFF)
1260 ewk_geolocation_permission_request_set(permissionRequest, EINA_FALSE);
1263 ViewModule::GeolocationSupport::geolocationPermissionRequest(
1265 This->m_securityOriginSupport->getSecurityOriginDAO(),
1269 void ViewLogic::notificationShowCallback(
1271 Evas_Object* /*obj*/,
1274 LogDebug("notificationShowCallback called");
1276 ViewLogic* This = static_cast<ViewLogic*>(data);
1279 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1281 using namespace ViewModule::WebNotification;
1283 WebNotificationDataPtr notiData(
1284 new WebNotificationData(
1286 ewk_notification_id_get(noti)));
1288 DPL::OptionalString string =
1289 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1290 if (!string.IsNull()) {
1291 notiData->m_iconURL = DPL::ToUTF8String(*string);
1293 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1294 if (!string.IsNull()) {
1295 notiData->m_title = DPL::ToUTF8String(*string);
1297 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1298 if (!string.IsNull()) {
1299 notiData->m_body = DPL::ToUTF8String(*string);
1302 LogInfo("notification id : " << notiData->m_id);
1303 LogInfo("notification iconURL : " << notiData->m_iconURL);
1304 LogInfo("notification title : " << notiData->m_title);
1305 LogInfo("notification body : " << notiData->m_body);
1307 showWebNotification(notiData);
1308 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1311 void ViewLogic::notificationCancelCallback(
1313 Evas_Object* /*obj*/,
1314 void* /*eventInfo*/)
1316 LogDebug("notificationCancelCallback called");
1319 void ViewLogic::notificationPermissionRequestCallback(
1321 Evas_Object* /*obj*/,
1324 LogDebug("notificationPermissionRequestCallback called");
1326 ViewLogic* This = static_cast<ViewLogic*>(data);
1327 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1328 WrtDB::FEATURE_WEB_NOTIFICATION)
1329 == WrtDB::SETTINGS_TYPE_OFF)
1331 Ewk_Notification_Permission_Request* request =
1332 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1333 ewk_notification_permission_request_set(
1340 ViewModule::WebNotification::webNotificationPermissionRequest(
1342 This->m_securityOriginSupport->getSecurityOriginDAO(),
1347 // EWK Orientation Callback
1348 Eina_Bool ViewLogic::orientationLockCallback(
1350 Eina_Bool /*needLock*/,
1354 LogDebug("orientationLockCallback called");
1356 ViewLogic* This = static_cast<ViewLogic*>(data);
1358 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1359 LogDebug("orientation is portrait-primary");
1360 elm_win_wm_rotation_preferred_rotation_set(
1362 WIN_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
1363 ewk_view_orientation_send(obj, W3C_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
1364 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1365 LogDebug("orientation is landscape-primary");
1366 elm_win_wm_rotation_preferred_rotation_set(
1368 WIN_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE);
1369 ewk_view_orientation_send(
1371 W3C_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE);
1372 } else if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1373 LogDebug("orientation is portrait-secondary");
1374 elm_win_wm_rotation_preferred_rotation_set(
1376 WIN_ORIENTATION_PORTRAIT_SECONDARY_ANGLE);
1377 ewk_view_orientation_send(
1379 W3C_ORIENTATION_PORTRAIT_SECONDARY_ANGLE);
1380 } else if (orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1381 LogDebug("orientation is landscape-secondary");
1382 elm_win_wm_rotation_preferred_rotation_set(
1384 WIN_ORIENTATION_LANDSCAPE_SECONDARY_ANGLE);
1385 ewk_view_orientation_send(
1387 W3C_ORIENTATION_LANDSCAPE_SECONDARY_ANGLE);
1389 LogDebug("Wrong orientation is set");
1395 // Fullscreen API callbacks
1396 void ViewLogic::enterFullscreenCallback(
1398 Evas_Object* /*obj*/,
1399 void* /*eventInfo*/)
1401 LogInfo("enterFullscreenCallback called");
1403 ViewLogic* This = static_cast<ViewLogic*>(data);
1404 if (!This->m_cbs->toggleFullscreen.empty()) {
1405 This->m_cbs->toggleFullscreen(true);
1408 void ViewLogic::exitFullscreenCallback(
1410 Evas_Object* /*obj*/,
1411 void* /*eventInfo*/)
1413 LogInfo("exitFullscreenCallback called");
1415 ViewLogic* This = static_cast<ViewLogic*>(data);
1416 if (!This->m_cbs->toggleFullscreen.empty()) {
1417 This->m_cbs->toggleFullscreen(false);
1421 void ViewLogic::imeChangedCallback(
1423 Evas_Object* /*obj*/,
1429 ViewLogic* This = static_cast<ViewLogic*>(data);
1430 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1431 This->m_imeWidth = rect->w;
1432 This->m_imeHeight = rect->h;
1435 void ViewLogic::imeOpenedCallback(
1437 Evas_Object* /*obj*/,
1438 void* /*eventInfo*/)
1442 ViewLogic* This = static_cast<ViewLogic*>(data);
1444 using namespace WrtPlugins::W3C;
1445 SoftKeyboardChangeArgs args;
1446 args.state = IME_STATE_ON;
1447 args.width = This->m_imeWidth;
1448 args.height = This->m_imeHeight;
1449 This->fireJavascriptEvent(
1450 static_cast<int>(SoftKeyboardChangeCustomEvent),
1454 void ViewLogic::imeClosedCallback(
1456 Evas_Object* /*obj*/,
1457 void* /*eventInfo*/)
1461 ViewLogic* This = static_cast<ViewLogic*>(data);
1463 using namespace WrtPlugins::W3C;
1464 SoftKeyboardChangeArgs args;
1465 args.state = IME_STATE_OFF;
1467 This->fireJavascriptEvent(
1468 static_cast<int>(SoftKeyboardChangeCustomEvent),
1472 void ViewLogic::usermediaPermissionRequestCallback(
1474 Evas_Object* /*obj*/,
1477 LogDebug("usermediaPermissionRequestCallback called");
1479 ViewLogic* This = static_cast<ViewLogic*>(data);
1480 ViewModule::UsermediaSupport::usermediaPermissionRequest(
1482 This->m_securityOriginSupport->getSecurityOriginDAO(),
1487 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1490 Ewk_Custom_Handlers_Data* handler =
1491 static_cast<Ewk_Custom_Handlers_Data*>(data);
1492 CustomHandlerDB::CustomHandlerPtr customHandler(
1493 new CustomHandlerDB::CustomHandler());
1494 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1496 LogDebug("base url: " << base_url);
1497 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1499 const char* url = ewk_custom_handlers_data_url_get(handler);
1501 LogDebug("url: " << url);
1502 customHandler->url = DPL::FromASCIIString(string(url));
1504 const char* target = ewk_custom_handlers_data_target_get(handler);
1506 LogDebug("target: " << target);
1507 customHandler->target = DPL::FromASCIIString(string(target));
1509 const char* title = ewk_custom_handlers_data_title_get(handler);
1511 LogDebug("title: " << title);
1512 customHandler->title = DPL::FromASCIIString(string(title));
1514 return customHandler;
1517 void ViewLogic::attachToCustomHandlersDao()
1519 if (!m_attachedToCustomHandlerDao) {
1520 CustomHandlerDB::Interface::attachDatabaseRW();
1524 void ViewLogic::detachFromCustomHandlersDao()
1526 if (m_attachedToCustomHandlerDao) {
1527 CustomHandlerDB::Interface::detachDatabase();
1531 const int protocolWhiteListLenth = 15;
1532 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1550 const int contentBlackListLenth = 14;
1551 char const * const contentBlackList[contentBlackListLenth] = {
1552 "application/x-www-form-urlencoded",
1553 "application/xhtml+xml",
1559 "multipart/x-mixed-replace",
1560 "text/cache-manifest",
1569 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1572 * @param customHandler
1574 void saveUserResponse(Wrt::Popup::PopupResponse response,
1575 CustomHandlerDB::CustomHandlerPtr customHandler)
1578 case Wrt::Popup::YES_DO_REMEMBER:
1579 LogDebug("User allowed, remember");
1580 customHandler->user_decision =
1581 static_cast<CustomHandlerDB::HandlerState>
1582 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1584 case Wrt::Popup::YES_DONT_REMEMBER:
1585 LogDebug("User allowed, don't remember");
1586 customHandler->user_decision = CustomHandlerDB::Agreed;
1588 case Wrt::Popup::NO_DO_REMEMBER:
1589 LogDebug("User didn't allow, remember");
1590 customHandler->user_decision =
1591 static_cast<CustomHandlerDB::HandlerState>
1592 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1594 case Wrt::Popup::NO_DONT_REMEMBER:
1595 LogDebug("User didn't allow, don't remember");
1596 customHandler->user_decision = CustomHandlerDB::Declined;
1601 //TODO registration, checking if registered and unregistration can be done in
1602 //common functions for both types of handlers. Only white and black lists
1603 //have to be separated
1604 //TODO attach database only one at the start (not in every callback?)
1605 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1606 Evas_Object* /*obj*/,
1611 CustomHandlerDB::CustomHandlerPtr customHandler =
1612 getCustomHandlerFromData(eventInfo);
1614 std::string scheme = DPL::ToUTF8String(customHandler->target);
1615 if (scheme.empty()) {
1616 LogError("No scheme provided");
1617 //TODO what about securityError?
1620 bool matched = false;
1621 //scheme on whiteList
1622 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1623 if (0 == strcmp(protocolWhiteList[i], scheme.c_str())) {
1624 LogDebug("Match found, protocol can be handled");
1629 //starts with web+ and have at least 5 chars (lowercase ASCII)
1630 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1631 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1632 //throw SecurityException
1638 if (c < 'a' || c > 'z') {
1639 LogWarning("Wrong char inside scheme. "
1640 << "Only lowercase ASCII letters accepted");
1641 //throw SecurityException
1648 ViewLogic* This = static_cast<ViewLogic*>(data);
1649 LogDebug("Creating handlers dao");
1650 This->attachToCustomHandlersDao();
1651 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1652 CustomHandlerDB::CustomHandlerPtr handler =
1653 handlersDao.getProtocolHandler(customHandler->target,
1655 customHandler->base_url);
1656 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1657 LogDebug("Protocol already registered - nothing to do");
1659 LogDebug("Protocol handler not found");
1660 Wrt::Popup::PopupResponse response =
1661 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1663 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1664 PROTOCOL_HANDLER_ASK_TITLE,
1665 PROTOCOL_HANDLER_ASK_MSG,
1666 PROTOCOL_HANDLER_ASK_REMEMBER);
1667 saveUserResponse(response, customHandler);
1668 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1671 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1672 //TODO remove old default handler somehow from appsvc
1673 LogDebug("Registering appservice entry");
1674 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1677 customHandler->target).c_str(),
1678 DPL::ToUTF8String(This->m_model->
1680 if (APPSVC_RET_OK != ret) {
1681 LogWarning("Appsvc entry failed: " << ret);
1682 //no database change
1686 handlersDao.registerProtocolHandler(*(customHandler.get()));
1688 LogDebug("Protocal saved");
1691 This->detachFromCustomHandlersDao();
1694 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1695 Evas_Object* /*obj*/,
1699 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(
1701 ViewLogic* This = static_cast<ViewLogic*>(data);
1702 LogDebug("Creating handlers dao");
1703 This->attachToCustomHandlersDao();
1704 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1705 CustomHandlerDB::CustomHandlerPtr handler =
1706 handlersDao.getProtocolHandler(customHandler->target,
1708 customHandler->base_url);
1710 if (handler->user_decision & CustomHandlerDB::Agreed) {
1711 ewk_custom_handlers_data_result_set(
1712 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1713 EWK_CUSTOM_HANDLERS_REGISTERED);
1715 ewk_custom_handlers_data_result_set(
1716 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1717 EWK_CUSTOM_HANDLERS_DECLINED);
1720 ewk_custom_handlers_data_result_set(
1721 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1722 EWK_CUSTOM_HANDLERS_NEW);
1724 This->detachFromCustomHandlersDao();
1727 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1728 Evas_Object* /*obj*/,
1732 CustomHandlerDB::CustomHandlerPtr customHandler =
1733 getCustomHandlerFromData(eventInfo);
1734 ViewLogic* This = static_cast<ViewLogic*>(data);
1735 LogDebug("Creating handlers dao");
1736 This->attachToCustomHandlersDao();
1737 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1738 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1739 handlersDao.getProtocolHandler(customHandler->target,
1741 customHandler->base_url);
1742 This->detachFromCustomHandlersDao();
1744 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1745 int ret = appsvc_unset_defapp(
1746 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1747 if (APPSVC_RET_OK != ret) {
1748 LogWarning("Failed to unregister appsvc entry");
1752 //if appsvc ok change custom_handlers_db
1753 handlersDao.unregisterProtocolHandler(customHandler->target,
1755 customHandler->base_url);
1757 LogDebug("Nothing to unregister");
1761 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1762 Evas_Object* /*obj*/,
1767 CustomHandlerDB::CustomHandlerPtr customHandler =
1768 getCustomHandlerFromData(eventInfo);
1770 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1771 if (mimeType.empty()) {
1772 LogError("No mimeType provided.");
1775 for (int i = 0; i < contentBlackListLenth; ++i) {
1776 if (0 == strcmp(contentBlackList[i], mimeType.c_str())) {
1777 LogWarning("mimeType blacklisted");
1778 //throw SecurityException
1783 ViewLogic* This = static_cast<ViewLogic*>(data);
1784 LogDebug("Creating handlers dao");
1785 This->attachToCustomHandlersDao();
1786 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1787 CustomHandlerDB::CustomHandlerPtr handler =
1788 handlersDao.getContentHandler(customHandler->target,
1790 customHandler->base_url);
1791 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1792 LogDebug("Protocol already registered - nothing to do");
1794 LogDebug("Protocol handler not found");
1795 Wrt::Popup::PopupResponse response =
1796 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::
1798 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1799 CONTENT_HANDLER_ASK_TITLE,
1800 CONTENT_HANDLER_ASK_MSG,
1801 CONTENT_HANDLER_AKS_REMEMBER);
1802 saveUserResponse(response, customHandler);
1803 if (customHandler->user_decision == CustomHandlerDB::Declined) {
1806 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1807 //TODO remove old default handler somehow from appsvc
1808 LogDebug("Registering appservice entry");
1809 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1811 customHandler->target).c_str(),
1813 DPL::ToUTF8String(This->m_model->
1815 if (APPSVC_RET_OK != ret) {
1816 LogWarning("Appsvc entry failed: " << ret);
1820 handlersDao.registerContentHandler(*(customHandler.get()));
1821 LogDebug("Content saved");
1823 This->detachFromCustomHandlersDao();
1826 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1827 Evas_Object* /*obj*/,
1831 CustomHandlerDB::CustomHandlerPtr customHandler =
1832 getCustomHandlerFromData(eventInfo);
1833 ViewLogic* This = static_cast<ViewLogic*>(data);
1834 LogDebug("Creating handlers dao");
1836 This->attachToCustomHandlersDao();
1837 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1838 CustomHandlerDB::CustomHandlerPtr handler =
1839 handlersDao.getContentHandler(customHandler->target,
1841 customHandler->base_url);
1843 if (handler->user_decision & CustomHandlerDB::Agreed) {
1844 ewk_custom_handlers_data_result_set(
1845 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1846 EWK_CUSTOM_HANDLERS_REGISTERED);
1848 ewk_custom_handlers_data_result_set(
1849 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1850 EWK_CUSTOM_HANDLERS_DECLINED);
1853 ewk_custom_handlers_data_result_set(
1854 static_cast<Ewk_Custom_Handlers_Data*>(eventInfo),
1855 EWK_CUSTOM_HANDLERS_NEW);
1857 This->detachFromCustomHandlersDao();
1860 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1861 Evas_Object* /*obj*/,
1865 CustomHandlerDB::CustomHandlerPtr customHandler =
1866 getCustomHandlerFromData(eventInfo);
1867 ViewLogic* This = static_cast<ViewLogic*>(data);
1868 LogDebug("Creating handlers dao");
1869 This->attachToCustomHandlersDao();
1870 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1871 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1872 handlersDao.getContentHandler(customHandler->target,
1874 customHandler->base_url);
1875 This->detachFromCustomHandlersDao();
1877 if (handlerCheck->user_decision & CustomHandlerDB::Agreed) {
1878 int ret = appsvc_unset_defapp(
1879 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1880 if (APPSVC_RET_OK != ret) {
1881 LogWarning("Failed to unregister mime handler from appsvc");
1885 handlersDao.unregisterContentHandler(customHandler->target,
1887 customHandler->base_url);
1889 LogDebug("Nothing to unregister");
1893 void ViewLogic::didRunJavaScriptCallback(
1894 Evas_Object* /*obj*/,
1898 LogInfo("didRunJavaScriptCallback called");
1899 LogInfo("result = " << result);
1902 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1904 LogDebug("closeIdlerCallback");
1905 ViewLogic* This = static_cast<ViewLogic*>(data);
1906 This->windowClose();
1907 return ECORE_CALLBACK_CANCEL;
1910 void ViewLogic::certificateConfirmRequestCallback(
1912 Evas_Object* /*obj*/,
1915 LogDebug("certificateConfirmRequestCallback called");
1918 ViewLogic* This = static_cast<ViewLogic*>(data);
1920 ViewModule::CertificateConfirmSupport::certificatePermissionRequest(
1922 This->m_certificateSupport->getCertificateDAO(),
1926 void ViewLogic::authenticationChallengeRequestCallback(
1928 Evas_Object* /*obj*/,
1931 LogDebug("authenticationChallengeRequestCallback called");
1934 ViewLogic* This = static_cast<ViewLogic*>(data);
1935 const char* url = ewk_view_url_get(This->m_currentEwkView);
1936 if (!url || strlen(url) == 0) {
1937 url = This->m_currentUri.c_str();
1940 ViewModule::AuthenticationChallengeSupport::authenticationChallengeRequest(
1941 This->m_currentEwkView,
1946 void ViewLogic::viewFrameRenderedCallback(
1948 Evas_Object* /*obj*/,
1949 void* /*eventInfo*/)
1954 std::string ViewLogic::requestUrlBlocked(const std::string& blockedUrl)
1958 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1959 // block this page and open it in browser
1960 LogDebug("Request was blocked by WARP: " << blockedUrl);
1961 LogDebug("open browser : " << blockedUrl);
1962 bundle* bundleData = bundle_create();
1963 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
1964 appsvc_set_uri(bundleData, blockedUrl.c_str());
1965 CONTROLLER_POST_EVENT(
1966 ApplicationLauncher,
1967 ApplicationLauncherEvents::LaunchApplicationByAppService(
1973 // set block url. This is used on load finished callback
1974 m_blockedUri = blockedUrl;
1976 // This is used in case of returning previous page
1977 return URICHANGE_PLUGIN_NO_CHANGE;
1980 std::string ViewLogic::requestUrlChanged(const std::string& changedUrl)
1982 using namespace ViewModule::SecuritySupport;
1984 LogInfo("changed url: " << changedUrl);
1986 // Check if this url with 'http' or 'https' is included in whitelist,
1987 // which has lists of accessible external documents and
1988 // used for ONLY Tizen app
1989 std::string matchedScheme;
1990 std::string matchedUri;
1991 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(changedUrl.c_str(),
1994 ViewModule::Scheme scheme(matchedScheme);
1995 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
1996 scheme.GetType() == ViewModule::Scheme::HTTPS)
1998 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1999 if (!checkWhitelist(changedUrl.c_str())) {
2000 LogInfo("This uri is not included in white document list");
2001 return URICHANGE_PLUGIN_STOP_ONLY;
2003 LogInfo("This url is included in WhiteList");
2005 // For WAC app, WRT should block access of device api
2006 // for external documents
2007 return URICHANGE_PLUGIN_STOP_ONLY;
2011 m_currentUri = changedUrl;
2012 return URICHANGE_PLUGIN_RESTART;
2015 void ViewLogic::windowClose()
2017 LogDebug("windowClose");
2018 Assert(m_closedEwkView && "no closed webview");
2020 if (1 >= m_ewkViewList.size()) {
2021 if (!m_cbs->webkitExit.empty()) {
2022 m_cbs->webkitExit();
2025 // call user callbacks
2026 if (!m_cbs->bufferUnset.empty()) {
2027 m_cbs->bufferUnset(m_currentEwkView);
2029 if (!m_cbs->windowClose.empty()) {
2030 m_cbs->windowClose(m_closedEwkView);
2032 removeEwkView(m_closedEwkView);
2034 // get latest ewkView
2035 m_currentEwkView = m_ewkViewList.back();
2036 const char* uri = ewk_view_url_get(m_currentEwkView);
2037 if (NULL == uri || 0 == strlen(uri)) {
2038 m_currentUri.clear();
2044 /* In case we support many pages in parallel
2045 * then view is not suspended*/
2046 //resumeEwkView(m_currentEwkView);
2047 setEwkViewVisible(m_currentEwkView);
2050 if (!m_cbs->bufferSet.empty()) {
2051 m_cbs->bufferSet(m_currentEwkView);