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>
36 #include <widget_model.h>
37 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
38 #include <dpl/utils/wrt_global_settings.h>
40 #include <common/application_data.h>
41 #include <common/application_launcher.h>
42 #include <common/scheme.h>
44 #include <common/view_logic_apps_support.h>
45 #include <common/view_logic_custom_header_support.h>
46 #include <common/view_logic_password_support.h>
47 #include <common/view_logic_security_support.h>
48 #include <common/view_logic_security_origin_support.h>
49 #include <common/view_logic_storage_support.h>
50 #include <common/view_logic_uri_support.h>
51 #include <common/view_logic_user_agent_support.h>
52 #include <common/view_logic_vibration_support.h>
53 #include <view_logic_scheme_support.h>
54 #include <view_logic_filesystem_support.h>
55 #include <view_logic_geolocation_support_webkit2.h>
56 #include <view_logic_usermedia_support.h>
57 #include <view_logic_web_notification_support.h>
58 #include <view_logic_web_storage_support.h>
59 #include "bundles/plugin_module_support.h"
60 #include <popup-runner/PopupInvoker.h>
63 #include <js_overlay_types.h>
64 #include <i_runnable_widget_object.h>
65 #include <profiling_util.h>
66 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
67 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
68 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
69 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
71 #include <appsvc/appsvc.h>
74 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
75 const char * const uriBlockedMessageName = "uri_block_msg";
76 const char * const uriChangedMessageName = "uri_changed_msg";
77 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
78 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
79 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
80 const char * const URICHANGE_BLOCKED_URL = "null";
81 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
82 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
84 const char * const IME_STATE_ON = "on";
85 const char * const IME_STATE_OFF = "off";
87 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
88 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
89 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
90 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
91 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
92 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
93 } // anonymous namespace
95 std::map<const std::string, const Evas_Smart_Cb> ViewLogic::m_ewkCallbacksMap =
97 {"load,started", &ViewLogic::loadStartedCallback},
98 {"load,finished", &ViewLogic::loadFinishedCallback},
99 {"title,changed", &ViewLogic::titleChangedCallback},
100 {"load,progress", &ViewLogic::loadProgressCallback},
101 {"load,progress,finished", &ViewLogic::loadProgressFinishedCallback},
102 {"process,crashed", &ViewLogic::processCrashedCallback},
104 {"create,window", &ViewLogic::createWindowCallback},
105 {"close,window", &ViewLogic::closeWindowCallback},
106 // WKPagePolicyClient
107 {"policy,navigation,decide", &ViewLogic::policyNavigationDecideCallback},
108 {"policy,newwindow,decide", &ViewLogic::policyNewWindowDecideCallback},
109 {"policy,response,decide", &ViewLogic::pageResponseDecideCallback},
110 // WKPageContextMenuClient
111 {"contextmenu,customize", &ViewLogic::contextmenuCustomizeCallback},
113 {"form,submit", &ViewLogic::formSubmitCallback},
114 // EWK Geolocation Callback
115 {"request,geolocation,permission", &ViewLogic::geolocationPermissionRequestCallback},
116 // EWK Notification Callback
117 {"notification,show", &ViewLogic::notificationShowCallback},
118 {"notification,cancel", &ViewLogic::notificationCancelCallback},
119 {"notification,permission,request", &ViewLogic::notificationPermissionRequestCallback},
120 // EWK Vibration Callback
121 {"vibration,vibrate", &ViewLogic::vibrationVibrateCallback},
122 {"vibration,cancel", &ViewLogic::vibrationCancelCallback},
124 {"database,quota,exceeded", &ViewLogic::databaseUsagePermissionRequestCallback},
125 {"filesystem,permission,request", &ViewLogic::fileSystemPermissionRequestCallback},
126 {"fullscreen,enterfullscreen", &ViewLogic::enterFullscreenCallback},
127 {"fullscreen,exitfullscreen", &ViewLogic::exitFullscreenCallback},
129 // when ime start to be showed on the webview,
130 // this callback will be called
131 {"inputmethod,changed", &ViewLogic::imeChangedCallback},
132 // this callback will be called
133 // when ime finishes to be showed on the webview
134 // "event_info" arg of this callback is always NULL point
135 // if web content should know size of ime,
136 // use "inputmethod,changed" instead of this.
138 {"editorclient,ime,opened", &ViewLogic::imeOpenedCallback},
139 // when ime finished to be hidden,
140 // this callback will be called
141 {"editorclient,ime,closed", &ViewLogic::imeClosedCallback},
142 // EWK Usermedia Callback
143 {"usermedia,permission,request", &ViewLogic::usermediaPermissionRequestCallback},
145 {"protocolhandler,registration,requested", &ViewLogic::protocolHandlerRegistrationCallback},
146 {"protocolhandler,isregistered", &ViewLogic::protocolHandlerIsRegisteredCallback},
147 {"protocolhandler,unregistration,requested", &ViewLogic::protocolHandlerUnregistrationCallback},
148 {"contenthandler,registration,requested", &ViewLogic::contentHandlerRegistrationCallback},
149 {"contenthandler,isregistered", &ViewLogic::contentHandlerIsRegisteredCallback},
150 {"contenthandler,unregistration,requested", &ViewLogic::contentHandlerUnregistrationCallback}
153 ViewLogic::ViewLogic():
158 m_cbs(new WRT::UserDelegates),
159 m_isBackgroundReload(false),
160 m_appsSupport(new ViewModule::AppsSupport()),
161 m_vibrationSupport(new ViewModule::VibrationSupport()),
162 m_attachedToCustomHandlerDao(false)
166 ViewLogic::~ViewLogic ()
168 detachFromCustomHandlersDao();
171 void ViewLogic::createWebView(Ewk_Context* context,
175 initializeEwkContext(context);
176 Assert(NULL != m_ewkContext);
179 createEwkView(evas_object_evas_get(m_window));
182 void ViewLogic::destroyWebView()
185 finalizeEwkContext();
189 void ViewLogic::initialize()
191 LogDebug("Initializing");
192 ApplicationLauncherSingleton::Instance().Touch();
193 appcore_set_event_callback(
194 APPCORE_EVENT_LOW_MEMORY,
195 &appcoreLowMemoryCallback,
199 void ViewLogic::terminate()
201 LogDebug("terminating view logic");
205 LogError("Widget model not created");
210 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
212 LogDebug("View prepare");
216 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
217 Assert(NULL != m_ewkContext);
220 ADD_PROFILING_POINT("initializeSupport", "start");
222 ADD_PROFILING_POINT("initializeSupport", "stop");
224 ewkClientInit(m_currentEwkView);
225 ADD_PROFILING_POINT("prepareEwkView", "start");
226 prepareEwkView(m_currentEwkView);
227 ADD_PROFILING_POINT("prepareEwkView", "stop");
228 initializePluginLoading();
231 void ViewLogic::showWidget()
233 LogDebug("showing widget");
234 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
235 if (m_currentUri.empty()) {
236 LogError("Localized current URI doesn't exist");
240 LogInfo("m_currentUri: " << m_currentUri);
243 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
245 if (!m_cbs->bufferSet.empty()) {
246 m_cbs->bufferSet(m_currentEwkView);
250 void ViewLogic::hideWidget()
252 LogDebug("hiding widget");
253 ViewModule::StorageSupport::deinitializeStorage(m_model);
254 m_appsSupport->deinitialize();
256 m_vibrationSupport->deinitialize();
258 while (m_ewkViewList.size()) {
259 LogInfo("pop webview: " << m_ewkViewList.back());
260 removeEwkView(m_ewkViewList.back());
262 m_ewkViewList.clear();
265 void ViewLogic::changeViewVisibility(bool isVisible)
267 Evas_Object* wkView = m_currentEwkView;
272 ewk_view_page_visibility_state_set(wkView,
273 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
275 ewk_view_visibility_set(wkView, EINA_TRUE);
277 ewk_view_page_visibility_state_set(wkView,
278 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
280 ewk_view_visibility_set(wkView, EINA_FALSE);
284 void ViewLogic::suspendWidget()
286 LogInfo("Pausing widget");
289 LogDebug("Request bundle to suspend");
290 PluginModuleSupport::suspend(m_ewkContext);
292 if (!m_currentEwkView) {
293 LogWarning("Cannot suspend widget without view");
295 suspendWebkit(m_currentEwkView);
298 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
300 // call user callback
301 if (!m_cbs->suspend.empty()) {
302 m_cbs->suspend(true);
306 void ViewLogic::resumeWidget()
308 LogInfo("Resume widget");
311 LogDebug("Request bundle to resume");
312 PluginModuleSupport::resume(m_ewkContext);
314 if (m_currentEwkView) {
315 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 // check if already created webview exists
337 if (!m_ewkViewList.size()) {
338 // create new webview
339 createEwkView(evas_object_evas_get(m_window));
341 ewkClientInit(m_currentEwkView);
342 prepareEwkView(m_currentEwkView);
344 // check if current url is service url for this tizen service
345 std::string requestedUri =
346 ViewModule::UriSupport::getUri(m_model, m_startUrl);
347 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
348 DPL::FromUTF8String(requestedUri.c_str()),
351 const char* currentUri = ewk_view_url_get(m_currentEwkView);
352 if (!currentUri && 0 == strlen(currentUri)) {
353 LogError("Fail to get uri from ewk_view_url_get");
358 PluginModuleSupport::resume(m_ewkContext);
359 resumeWebkit(m_currentEwkView);
360 if (DPL::ToUTF8String(*servicedUri) == currentUri) {
361 LogInfo("current page is raised");
362 // set only encoded bundle
363 double scale = elm_config_scale_get();
364 PluginModuleSupport::setCustomProperties(
367 ApplicationDataSingleton::Instance().getEncodedBundle());
368 PluginModuleSupport::dispatchJavaScriptEvent(
370 WrtPlugins::W3C::ServiceCustomEvent,
373 LogInfo("service page is loaded");
374 m_currentUri = DPL::ToUTF8String(*servicedUri);
375 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
377 elm_win_activate(m_window);
378 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
381 // call user callback
382 if (!m_cbs->reset.empty()) {
385 if (!m_cbs->bufferSet.empty()) {
386 m_cbs->bufferSet(m_currentEwkView);
390 void ViewLogic::backward()
392 if (ewk_view_back_possible(m_currentEwkView)) {
393 ewk_view_back(m_currentEwkView);
395 if (1 >= m_ewkViewList.size()) {
396 // If there is no previous page, widget move to backgroud.
397 LogInfo("Widget move to backgroud");
398 elm_win_lower(m_window);
400 // Back to previous webview
401 LogInfo("Widget move to previous webview");
402 ecore_idler_add(windowCloseIdlerCallback, this);
407 void ViewLogic::reloadStartPage()
409 LogInfo("Reload Start Page");
410 // prevent fail to load plugin bundle side
411 m_isBackgroundReload = true;
412 PluginModuleSupport::resume(m_ewkContext);
414 if (m_ewkViewList.size() != 0) {
415 while (m_ewkViewList.size() > 0) {
416 if (!m_cbs->bufferUnset.empty()) {
417 m_cbs->bufferUnset(m_currentEwkView);
419 removeEwkView(m_currentEwkView);
423 // create new webview
424 createEwkView(evas_object_evas_get(m_window));
425 ewkClientInit(m_currentEwkView);
428 prepareEwkView(m_currentEwkView);
429 initializePluginLoading();
432 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
435 if (!m_cbs->bufferSet.empty()) {
436 m_cbs->bufferSet(m_currentEwkView);
438 LogInfo("Reloading Start Page is done!");
441 Evas_Object* ViewLogic::getCurrentWebview()
443 LogInfo("get current webview");
444 return m_currentEwkView;
447 void ViewLogic::fireJavascriptEvent(int event, void* data)
449 PluginModuleSupport::dispatchJavaScriptEvent(
451 static_cast<WrtPlugins::W3C::CustomEventType>(event),
455 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
460 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
462 LogInfo("initializeEwkContext called");
463 Assert(newEwkContext && "Ewk_Context provided can not be null");
464 // bundle callback setting
465 ewk_context_message_from_injected_bundle_callback_set(
467 contextMessageFromInjectedBundleCallback,
468 static_cast<void*>(this));
470 // proxy server setting
471 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
472 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
473 || (strstr(proxyAddress, "0.0.0.0")))
475 LogInfo("proxy address is empty");
476 ewk_context_proxy_uri_set(newEwkContext, NULL);
478 LogInfo("proxy address [" << proxyAddress << "]");
479 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
488 const char *theme = elm_theme_get(NULL);
491 LogInfo("theme is " << m_theme);
494 // Ewk download callback (WKContextDownloadClient)
495 ewk_context_did_start_download_callback_set(
497 didStartDownloadCallback,
500 // set to member value
501 m_ewkContext = newEwkContext;
504 void ViewLogic::finalizeEwkContext()
506 LogInfo("finalizeEwkContext called");
507 ewk_context_message_from_injected_bundle_callback_set(
511 // ewk_context_delete(m_ewkContext);
515 void ViewLogic::initializeSupport()
517 // set local stroage database path
518 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
519 ewk_context_web_storage_path_set(m_ewkContext,
520 dao.getPrivateLocalStoragePath().c_str());
521 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
522 ViewModule::StorageSupport::initializeStorage(m_model);
523 m_appsSupport->initialize(m_model);
524 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
526 m_vibrationSupport->initialize();
529 void ViewLogic::initializePluginLoading()
531 // inform wrt information for plugin loading to web process
532 PluginModuleSupport::start(
535 elm_config_scale_get(),
536 ApplicationDataSingleton::Instance().getEncodedBundle(),
538 m_model->SettingList.Get().isEncrypted());
541 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
542 Assert(NULL != wkView && "ewk_view not created at this point");
544 FOREACH(it, m_ewkCallbacksMap) {
545 evas_object_smart_callback_add(
553 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
554 LogDebug("ewkClientDeinit");
555 Assert(NULL != wkView && "ewk_view not created at this point");
557 FOREACH(it, m_ewkCallbacksMap) {
558 evas_object_smart_callback_del(
565 void ViewLogic::createEwkView(Evas* canvas)
567 LogDebug("createEwkVeiw");
569 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
570 Evas_Object* newEwkView = ewk_view_add_with_context(
573 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
576 LogError("WKView creation failed");
581 // even arguments pass the ewkContext, this API should be called
582 // after webkit Evas_Object is created
583 Ewk_Cookie_Manager *ewkCookieManager;
585 ewk_context_cookie_manager_get(m_ewkContext);
586 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
587 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
589 LogInfo("push webview: " << newEwkView);
590 m_ewkViewList.push_back(newEwkView);
591 m_currentEwkView = newEwkView;
594 void ViewLogic::setStartPage()
596 /* Start URI (as other uris) is now localized
597 * on WebProcess side */
598 m_currentUri = m_startUrl;
601 void ViewLogic::prepareEwkView(Evas_Object *wkView)
603 LogDebug("prepareEwkView called");
605 Ewk_Settings* settings = ewk_view_settings_get(wkView);
608 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
609 if (customUserAgent.empty()) {
610 auto userAgentString =
611 ViewModule::UserAgentSupport::getUserAgentFromVconf();
612 if (!userAgentString.empty()) {
613 LogDebug("Setting user agent as: " << userAgentString);
614 ewk_view_user_agent_set(wkView, userAgentString.c_str());
617 LogDebug("Setting custom user agent as: " << customUserAgent);
618 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
621 // set custom header : language
622 using namespace ViewModule::CustomHeaderSupport;
623 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
624 if (!customHeaderString.empty()) {
625 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
626 LogDebug("custom value=[" << customHeaderString << "]");
627 ewk_view_custom_header_add(wkView,
628 ACCEPT_LANGUAGE.c_str(),
629 customHeaderString.c_str());
632 // webkit NPAPI plugins is always on in wrt
633 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
635 // The followings are not implemeted yet by webkit2
636 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
637 // ewk_view_mode_set();
638 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
639 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
640 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
641 // elm_webview_show_magnifier_set(EINA_FALSE);
642 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
643 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
644 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
646 // disable zoom option when user click the input field
647 // this option is useful with the normal website
648 // for the make user friendly, disable auto zoom in the webapp
649 // The followings are not implemeted yet by webkit2
650 // elm_webview_input_field_zoom_set(EINA_FALSE);
652 // set cookie database path
653 // The followings are not implemeted yet by webkit2
654 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
656 // set visibility to WebCore. This value will be used for html5.
657 // also, this value will be changed in the suspend, resume
658 // or create window, close window.
659 ewk_view_page_visibility_state_set(wkView,
660 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
664 void ViewLogic::removeEwkView(Evas_Object *wkView)
666 LogInfo("removeEwkView called");
668 Assert(0 != m_ewkViewList.size());
670 // unregister webview callbacks
671 ewkClientDeinit(wkView);
673 // suspend NPAPI plugin - Not implemented by Webkit2
674 // ewk_view_pause_or_resume_plugins();
675 evas_object_del(wkView);
676 m_ewkViewList.remove(wkView);
679 void ViewLogic::resumeEwkView(Evas_Object *wkView)
681 LogInfo("resumeEwkView called");
684 // register webview callback
685 ewkClientInit(wkView);
688 resumeWebkit(wkView);
693 void ViewLogic::suspendEwkView(Evas_Object *wkView)
695 LogInfo("suspendEwkView called");
699 suspendWebkit(wkView);
701 // unregister webview callbacks
702 ewkClientDeinit(wkView);
707 void ViewLogic::resumeWebkit(Evas_Object *wkView)
709 LogDebug("resumeWebkit");
712 // resume NPAPI plugin
713 // The followings are not implemeted yet by webkit2
714 // ewk_view_pause_or_resume_plugins(false);
715 // ewk_view_pause_or_resume_video_audio(false);
716 // ewk_view_javascript_resume();
717 // ewk_view_enable_render();
718 // ewk_view_reduce_plugins_frame_rate(false);
719 ewk_view_resume(wkView);
720 ewk_view_visibility_set(wkView, EINA_TRUE);
721 ewk_view_page_visibility_state_set(wkView,
722 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
727 void ViewLogic::suspendWebkit(Evas_Object *wkView)
729 LogDebug("suspendWebkit");
732 // suspend the followings
733 // The followings are not implemeted yet by webkit2
734 // ewk_view_pause_or_resume_plugins(true);
735 // ewk_view_pause_or_resume_video_audio(true);
736 ewk_view_suspend(wkView);
741 void ViewLogic::contextMessageFromInjectedBundleCallback(
747 LogDebug("contextMessageFromInjectedBundleCallback called");
749 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
750 // didRecieveMessageFromInjectedBundleCallback - returnData is null
751 // didReceiveSynchronousMessageCallback - returnData isn't null
752 // WKContextInjectedBundleClient bundleClient = {
753 // kWKContextInjectedBundleClientCurrentVersion,
754 // static_cast<void*>(this),
755 // &didRecieveMessageFromInjectedBundleCallback,
756 // &didReceiveSynchronousMessageCallback
758 if (NULL == returnData) {
759 This->didRecieveMessageFromInjectedBundle(name, body);
761 This->didReceiveSynchronousMessage(name, body, returnData);
765 void ViewLogic::didStartDownloadCallback(
766 const char* downloadUrl,
769 LogDebug("didStartDownloadCallback called");
771 ViewLogic* This = static_cast<ViewLogic*>(data);
773 LogDebug("download url = " << downloadUrl);
774 This->m_appsSupport->downloadRequest(
780 void ViewLogic::loadStartedCallback(
785 LogDebug("loadStartedCallback called");
787 ViewLogic* This = static_cast<ViewLogic*>(data);
788 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
790 // call loadFinish callback to wrt-client
791 if (!This->m_cbs->loadStart.empty()) {
792 This->m_cbs->loadStart(obj);
797 void ViewLogic::loadFinishedCallback(
802 LogDebug("loadFinishedCallback called");
804 ViewLogic* This = static_cast<ViewLogic*>(data);
807 const char* url = ewk_view_url_get(This->m_currentEwkView);
808 if (NULL == url || strlen(url) == 0) {
809 LogError("url is empty");
811 DPL::OptionalString jsOptionalString =
812 ViewModule::PasswordSupport::jsForAutoFillData(url);
813 if (jsOptionalString.IsNull()) {
814 LogError("Fail to get JS String");
816 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
818 if(EINA_FALSE == ewk_view_script_execute(
819 This->m_currentEwkView,
821 didRunJavaScriptCallback,
824 LogError("JS for auto fill data failed.");
829 // call loadFinish callback to wrt-client
830 if (!This->m_cbs->loadFinish.empty()) {
831 This->m_cbs->loadFinish(obj);
834 // set only encoded bundle
835 double scale = elm_config_scale_get();
836 PluginModuleSupport::setCustomProperties(
839 ApplicationDataSingleton::Instance().getEncodedBundle());
840 // check if 'appsevice' event is registed at the current frames.
841 // If so, dispatch the event to frames.
842 PluginModuleSupport::dispatchJavaScriptEvent(
844 WrtPlugins::W3C::ServiceCustomEvent,
847 // In this case, widget is reloaded in the background.
848 // After finished load, bundle should disconnent callback.
849 if (This->m_isBackgroundReload) {
850 PluginModuleSupport::suspend(This->m_ewkContext);
851 ewk_view_suspend(This->m_currentEwkView);
852 This->m_isBackgroundReload = false;
856 void ViewLogic::titleChangedCallback(
858 Evas_Object* /*obj*/,
861 LogDebug("titleChangedCallback called");
863 ViewLogic* This = static_cast<ViewLogic*>(data);
865 const char* title = static_cast<char*>(eventInfo);
867 if (0 == strlen(title)) {
868 LogDebug("title data is empty");
871 LogDebug("Title = [" << title << "]");
872 This->m_schemeSupport->HandleTizenScheme(title,
874 This->m_currentEwkView);
877 void ViewLogic::loadProgressCallback(
879 Evas_Object* /*obj*/,
882 double* progress = static_cast<double*>(eventInfo);
883 LogDebug("didChangeProgressCallback progress = " << *progress);
886 void ViewLogic::loadProgressFinishedCallback(
888 Evas_Object* /*obj*/,
891 LogDebug("didFinishProgressCallback");
893 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
894 if (!view->m_cbs->progressFinish.empty()) {
895 view->m_cbs->progressFinish();
899 void ViewLogic::processCrashedCallback(
901 Evas_Object* /*obj*/,
904 LogInfo("processCrashedCallback");
906 ViewLogic const * const view =
907 static_cast<ViewLogic const * const>(data);
908 if (!view->m_cbs->webCrash.empty()) {
909 view->m_cbs->webCrash();
911 // This flag will be prevented exit() call in the Webkit side
912 if (NULL != eventInfo) {
913 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
917 void ViewLogic::createWindowCallback(
922 LogDebug("createWindowCallback");
924 ViewLogic* This = static_cast<ViewLogic*>(data);
926 // First, current webview should be handled by user callback
927 if (!This->m_cbs->bufferUnset.empty()) {
928 This->m_cbs->bufferUnset(obj);
931 // this can be set by executable for specific purpose
933 if (!This->m_cbs->windowCreateBefore.empty()) {
934 // 'obj' is parent webview object
935 This->m_cbs->windowCreateBefore(&canvas, obj);
938 canvas = evas_object_evas_get(This->m_window);
941 // create new ewkview
942 This->createEwkView(canvas);
943 Evas_Object* newEwkView = This->m_currentEwkView;
945 // initialize new ewkview
946 This->setStartPage();
947 This->ewkClientInit(newEwkView);
948 This->prepareEwkView(newEwkView);
950 // Specific jobs of child, parent webview are handled by each executable
951 if (!This->m_cbs->windowCreateAfter.empty()) {
952 // 'obj' is parent webview, 'newEwkView' is child webview
953 This->m_cbs->windowCreateAfter(obj, newEwkView);
956 // Lastly, new webview should be handled by user callback
957 if (!This->m_cbs->bufferSet.empty()) {
958 This->m_cbs->bufferSet(newEwkView);
960 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
963 void ViewLogic::closeWindowCallback(
968 LogDebug("closeWindowCallback");
969 ViewLogic* This = static_cast<ViewLogic*>(data);
970 This->m_closedEwkView = obj;
971 ecore_idler_add(windowCloseIdlerCallback, This);
974 void ViewLogic::policyNavigationDecideCallback(
976 Evas_Object* /*obj*/,
979 LogDebug("policyNavigationDecideCallback called");
981 ViewLogic* This = static_cast<ViewLogic*>(data);
983 Ewk_Policy_Decision* policyDecision =
984 static_cast<Ewk_Policy_Decision*>(eventInfo);
986 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
990 This->m_currentEwkView))
993 ewk_policy_decision_use(policyDecision);
995 // check whether this is new empty window
996 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
997 if(!activeUrl || 0 == strlen(activeUrl)) {
999 * The view is empty and scheme has been handled externally. When
1000 * user gets back from the external application he'd see blank page
1001 * and won't be able to navigate back. This happens when window.open
1002 * is used to handle schemes like sms/mms/mailto (for example in
1003 * WAC web standards tests: WS-15XX).
1005 * To solve the problem, the empty view is removed from the stack
1006 * and the previous one is shown. This is not an elegant solution
1007 * but we don't have a better one.
1009 LogInfo("Scheme has been handled externally. Removing empty view.");
1010 if (ewk_view_back_possible(This->m_currentEwkView)) {
1011 // go back to previous WKPage
1012 ewk_view_back(This->m_currentEwkView);
1014 // stop current WKPage
1015 ewk_view_stop(This->m_currentEwkView);
1016 ecore_idler_add(windowCloseIdlerCallback, This);
1021 ewk_policy_decision_ignore(policyDecision);
1025 void ViewLogic::policyNewWindowDecideCallback(
1027 Evas_Object* /*obj*/,
1030 LogDebug("policyNewWindowDecideCallback called");
1032 ViewLogic* This = static_cast<ViewLogic*>(data);
1034 Ewk_Policy_Decision* policyDecision =
1035 static_cast<Ewk_Policy_Decision*>(eventInfo);
1037 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1041 This->m_currentEwkView))
1043 ewk_policy_decision_use(policyDecision);
1046 ewk_policy_decision_ignore(policyDecision);
1050 void ViewLogic::pageResponseDecideCallback(
1052 Evas_Object* /*obj*/,
1055 LogDebug("pageResponseDecideCallback called");
1057 ViewLogic* This = static_cast<ViewLogic*>(data);
1059 Ewk_Policy_Decision* policyDecision =
1060 static_cast<Ewk_Policy_Decision*>(eventInfo);
1061 Ewk_Policy_Decision_Type policyDecisionType =
1062 ewk_policy_decision_type_get(policyDecision);
1064 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1066 ewk_policy_decision_use(policyDecision);
1067 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1068 LogDebug("download");
1069 ewk_policy_decision_suspend(policyDecision);
1071 // get uri information
1072 const char* url = ewk_policy_decision_url_get(policyDecision);
1073 if (NULL == url || strlen(url) == 0) {
1074 LogDebug("url data is empty");
1075 ewk_policy_decision_use(policyDecision);
1078 LogDebug("url = [" << url << "]");
1080 // get content information
1081 const char* content =
1082 ewk_policy_decision_response_mime_get(policyDecision);
1083 LogDebug("content type = [" << content << "]");
1085 // get cookie information
1086 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1087 LogDebug("cookie = [" << cookie << "]");
1089 LogDebug("Content not supported, will be opened in external app");
1090 This->m_appsSupport->downloadRequest(
1094 ewk_policy_decision_ignore(policyDecision);
1095 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1097 ewk_policy_decision_ignore(policyDecision);
1099 LogDebug("Type isn't handled");
1100 ewk_policy_decision_ignore(policyDecision);
1104 void ViewLogic::contextmenuCustomizeCallback(
1106 Evas_Object* /*obj*/,
1109 LogDebug("contextmenuCustomizeCallback called");
1112 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1113 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1114 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1115 (This->m_model->SettingList.Get().getContextMenu()
1116 == ContextMenu_Disable))
1118 LogDebug("ContextMenu Disable!!");
1119 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1120 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1122 ewk_context_menu_item_remove(menu, item);
1125 LogDebug("ContextMenu Enable!!");
1126 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1127 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1129 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1132 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1133 ewk_context_menu_item_remove(menu, item);
1136 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1137 ewk_context_menu_item_remove(menu, item);
1148 void ViewLogic::formSubmitCallback(
1150 Evas_Object* /*obj*/,
1153 LogDebug("formSubmitCallback called");
1155 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1157 const char* uri = ewk_form_data_url_get(formData);
1159 LogError("URL is empty");
1163 Eina_Hash* userData = ewk_form_data_values_get(formData);
1164 ViewModule::PasswordSupport::submitClicked(uri, userData);
1167 void ViewLogic::geolocationPermissionRequestCallback(
1169 Evas_Object* /*obj*/,
1173 ViewLogic* This = static_cast<ViewLogic*>(data);
1175 Ewk_Geolocation_Permission_Data* permissionRequest =
1176 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1178 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1179 SecurityOriginDB::FEATURE_GEOLOCATION)
1180 == WrtDB::SETTINGS_TYPE_OFF)
1182 ewk_geolocation_permission_request_allow_set(
1183 ewk_geolocation_permission_request_get(permissionRequest),
1187 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1189 This->m_securityOriginSupport->getSecurityOriginDAO(),
1193 void ViewLogic::notificationShowCallback(
1195 Evas_Object* /*obj*/,
1198 LogDebug("notificationShowCallback called");
1200 ViewLogic* This = static_cast<ViewLogic*>(data);
1203 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1205 using namespace ViewModule::WebNotification;
1207 WebNotificationDataPtr notiData(
1208 new WebNotificationData(
1210 ewk_notification_id_get(noti)));
1212 DPL::OptionalString string =
1213 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1214 if (!string.IsNull()) {
1215 notiData->m_iconURL = DPL::ToUTF8String(*string);
1217 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1218 if (!string.IsNull()) {
1219 notiData->m_title = DPL::ToUTF8String(*string);
1221 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1222 if (!string.IsNull()) {
1223 notiData->m_body = DPL::ToUTF8String(*string);
1226 LogInfo("notification id : " << notiData->m_id);
1227 LogInfo("notification iconURL : " << notiData->m_iconURL);
1228 LogInfo("notification title : " << notiData->m_title);
1229 LogInfo("notification body : " << notiData->m_body);
1231 showWebNotification(notiData);
1232 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1235 void ViewLogic::notificationCancelCallback(
1237 Evas_Object* /*obj*/,
1238 void* /*eventInfo*/)
1240 LogDebug("notificationCancelCallback called");
1243 void ViewLogic::notificationPermissionRequestCallback(
1245 Evas_Object* /*obj*/,
1248 LogDebug("notificationPermissionRequestCallback called");
1250 ViewLogic* This = static_cast<ViewLogic*>(data);
1251 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1252 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1253 == WrtDB::SETTINGS_TYPE_OFF)
1255 Ewk_Notification_Permission_Request* request =
1256 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1257 ewk_notification_permission_request_response(
1265 ViewModule::WebNotification::webNotificationPermissionRequest(
1267 This->m_securityOriginSupport->getSecurityOriginDAO(),
1273 void ViewLogic::vibrationVibrateCallback(
1275 Evas_Object* /*obj*/,
1278 LogDebug("vibrationVibrateCallback called");
1280 ViewLogic* This = static_cast<ViewLogic*>(data);
1283 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1285 This->m_vibrationSupport->startVibration(vibrationTime);
1290 void ViewLogic::vibrationCancelCallback(
1292 Evas_Object* /*obj*/,
1293 void* /*eventInfo*/)
1295 LogDebug("vibrationCancelCallback called");
1297 ViewLogic* This = static_cast<ViewLogic*>(data);
1299 This->m_vibrationSupport->stopVibration();
1304 // EWK Orientation Callback
1305 Eina_Bool ViewLogic::orientationLockCallback(
1307 Eina_Bool /*needLock*/,
1311 LogDebug("orientationLockCallback called");
1313 ViewLogic* This = static_cast<ViewLogic*>(data);
1315 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1316 LogDebug("orientation is portrait-primary");
1317 elm_win_rotation_with_resize_set(This->m_window, 0);
1318 ewk_view_orientation_send(obj, 0);
1319 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1320 LogDebug("orientation is landscape-primary");
1321 elm_win_rotation_with_resize_set(This->m_window, 270);
1322 ewk_view_orientation_send(obj, 90);
1323 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1324 LogDebug("orientation is portrait-secondary");
1325 elm_win_rotation_with_resize_set(This->m_window, 180);
1326 ewk_view_orientation_send(obj, 180);
1327 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1328 LogDebug("orientation is landscape-secondary");
1329 elm_win_rotation_with_resize_set(This->m_window, 90);
1330 ewk_view_orientation_send(obj, -90);
1332 LogDebug("Wrong orientation is set");
1339 // Fullscreen API callbacks
1340 void ViewLogic::enterFullscreenCallback(
1342 Evas_Object* /*obj*/,
1343 void* /*eventInfo*/)
1345 LogInfo("enterFullscreenCallback called");
1347 ViewLogic* This = static_cast<ViewLogic*>(data);
1348 if (!This->m_cbs->toggleFullscreen.empty()) {
1349 This->m_cbs->toggleFullscreen(true);
1352 void ViewLogic::exitFullscreenCallback(
1354 Evas_Object* /*obj*/,
1355 void* /*eventInfo*/)
1357 LogInfo("exitFullscreenCallback called");
1359 ViewLogic* This = static_cast<ViewLogic*>(data);
1360 if (!This->m_cbs->toggleFullscreen.empty()) {
1361 This->m_cbs->toggleFullscreen(false);
1365 void ViewLogic::imeChangedCallback(
1367 Evas_Object* /*obj*/,
1373 ViewLogic* This = static_cast<ViewLogic*>(data);
1374 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1375 This->m_imeWidth = rect->w;
1376 This->m_imeHeight = rect->h;
1379 void ViewLogic::imeOpenedCallback(
1381 Evas_Object* /*obj*/,
1382 void* /*eventInfo*/)
1386 ViewLogic* This = static_cast<ViewLogic*>(data);
1388 using namespace WrtPlugins::W3C;
1389 SoftKeyboardChangeArgs args;
1390 args.state = IME_STATE_ON;
1391 args.width = This->m_imeWidth;
1392 args.height = This->m_imeHeight;
1393 This->fireJavascriptEvent(
1394 static_cast<int>(SoftKeyboardChangeCustomEvent),
1398 void ViewLogic::imeClosedCallback(
1400 Evas_Object* /*obj*/,
1401 void* /*eventInfo*/)
1405 ViewLogic* This = static_cast<ViewLogic*>(data);
1407 using namespace WrtPlugins::W3C;
1408 SoftKeyboardChangeArgs args;
1409 args.state = IME_STATE_OFF;
1411 This->fireJavascriptEvent(
1412 static_cast<int>(SoftKeyboardChangeCustomEvent),
1416 void ViewLogic::usermediaPermissionRequestCallback(
1418 Evas_Object* /*obj*/,
1421 LogDebug("usermediaPermissionRequestCallback called");
1423 ViewLogic* This = static_cast<ViewLogic*>(data);
1424 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1430 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1433 Ewk_Custom_Handlers_Data* handler =
1434 static_cast<Ewk_Custom_Handlers_Data*>(data);
1435 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1436 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1438 LogDebug("base url: " << base_url);
1439 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1441 const char* url = ewk_custom_handlers_data_url_get(handler);
1443 LogDebug("url: " << url);
1444 customHandler->url = DPL::FromASCIIString(string(url));
1446 const char* target = ewk_custom_handlers_data_target_get(handler);
1448 LogDebug("target: " << target);
1449 customHandler->target = DPL::FromASCIIString(string(target));
1451 const char* title = ewk_custom_handlers_data_title_get(handler);
1453 LogDebug("title: " << title);
1454 customHandler->title = DPL::FromASCIIString(string(title));
1456 return customHandler;
1459 void ViewLogic::attachToCustomHandlersDao()
1461 if (!m_attachedToCustomHandlerDao) {
1462 CustomHandlerDB::Interface::attachDatabaseRW();
1466 void ViewLogic::detachFromCustomHandlersDao()
1468 if (m_attachedToCustomHandlerDao) {
1469 CustomHandlerDB::Interface::detachDatabase();
1473 const int protocolWhiteListLenth = 15;
1474 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1492 const int contentBlackListLenth = 14;
1493 char const * const contentBlackList[contentBlackListLenth] = {
1494 "application/x-www-form-urlencoded",
1495 "application/xhtml+xml",
1501 "multipart/x-mixed-replace",
1502 "text/cache-manifest",
1511 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1514 * @param customHandler
1516 void saveUserResponse(Wrt::Popup::PopupResponse response,
1517 CustomHandlerDB::CustomHandlerPtr customHandler)
1520 case Wrt::Popup::YES_DO_REMEMBER:
1521 LogDebug("User allowed, remember");
1522 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1523 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1525 case Wrt::Popup::YES_DONT_REMEMBER:
1526 LogDebug("User allowed, don't remember");
1527 customHandler->user_decision = CustomHandlerDB::Agreed;
1529 case Wrt::Popup::NO_DO_REMEMBER:
1530 LogDebug("User didn't allow, remember");
1531 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1532 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1534 case Wrt::Popup::NO_DONT_REMEMBER:
1535 LogDebug("User didn't allow, don't remember");
1536 customHandler->user_decision = CustomHandlerDB::Declined;
1541 //TODO registration, checking if registered and unregistration can be done in
1542 //common functions for both types of handlers. Only white and black lists
1543 //have to be separated
1544 //TODO attach database only one at the start (not in every callback?)
1545 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1551 CustomHandlerDB::CustomHandlerPtr customHandler =
1552 getCustomHandlerFromData(eventInfo);
1554 std::string scheme = DPL::ToUTF8String(customHandler->target);
1555 if (scheme.empty()) {
1556 LogError("No scheme provided");
1557 //TODO what about securityError?
1560 bool matched = false;
1561 //scheme on whiteList
1562 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1563 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1565 LogDebug("Match found, protocol can be handled");
1570 //starts with web+ and have at least 5 chars (lowercase ASCII)
1571 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1572 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1573 //throw SecurityException
1580 if (c < 'a' || c > 'z') {
1581 LogWarning("Wrong char inside scheme. "
1582 << "Only lowercase ASCII letters accepted");
1583 //throw SecurityException
1590 ViewLogic* This = static_cast<ViewLogic*>(data);
1591 LogDebug("Creating handlers dao");
1592 This->attachToCustomHandlersDao();
1593 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1594 CustomHandlerDB::CustomHandlerPtr handler =
1595 handlersDao.getProtocolHandler(customHandler->target,
1597 customHandler->base_url);
1598 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1599 LogDebug("Protocol already registered - nothing to do");
1601 LogDebug("Protocol handler not found");
1602 Wrt::Popup::PopupResponse response =
1603 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1604 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1605 PROTOCOL_HANDLER_ASK_TITLE,
1606 PROTOCOL_HANDLER_ASK_MSG,
1607 PROTOCOL_HANDLER_ASK_REMEMBER);
1608 saveUserResponse(response, customHandler);
1609 if (customHandler->user_decision == CustomHandlerDB::Declined)
1611 handlersDao.registerProtocolHandler(*(customHandler.get()));
1612 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1613 //TODO remove old default handler somehow from appsvc
1614 LogDebug("Registering appservice entry");
1615 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1617 DPL::ToUTF8String(customHandler->target).c_str(),
1618 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1619 if (APPSVC_RET_OK != ret)
1621 LogWarning("Appsvc entry failed: " << ret);
1624 LogDebug("Protocal saved");
1627 This->detachFromCustomHandlersDao();
1630 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1635 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1636 ViewLogic* This = static_cast<ViewLogic*>(data);
1637 LogDebug("Creating handlers dao");
1638 This->attachToCustomHandlersDao();
1639 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1640 CustomHandlerDB::CustomHandlerPtr handler =
1641 handlersDao.getProtocolHandler(customHandler->target,
1643 customHandler->base_url);
1645 if (handler->user_decision & CustomHandlerDB::Agreed)
1646 ewk_custom_handlers_data_result_set(
1647 static_cast<Ewk_Custom_Handlers_Data*>(data),
1648 EWK_CUSTOM_HANDLERS_REGISTERED);
1650 ewk_custom_handlers_data_result_set(
1651 static_cast<Ewk_Custom_Handlers_Data*>(data),
1652 EWK_CUSTOM_HANDLERS_DECLINED);
1654 ewk_custom_handlers_data_result_set(
1655 static_cast<Ewk_Custom_Handlers_Data*>(data),
1656 EWK_CUSTOM_HANDLERS_NEW);
1657 This->detachFromCustomHandlersDao();
1660 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1665 CustomHandlerDB::CustomHandlerPtr customHandler =
1666 getCustomHandlerFromData(eventInfo);
1667 ViewLogic* This = static_cast<ViewLogic*>(data);
1668 LogDebug("Creating handlers dao");
1669 This->attachToCustomHandlersDao();
1670 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1671 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1672 handlersDao.getProtocolHandler(customHandler->target,
1674 customHandler->base_url);
1676 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1677 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1679 handlersDao.unregisterProtocolHandler(customHandler->target,
1681 customHandler->base_url);
1683 LogDebug("Nothing to unregister");
1685 This->detachFromCustomHandlersDao();
1688 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1694 CustomHandlerDB::CustomHandlerPtr customHandler =
1695 getCustomHandlerFromData(eventInfo);
1697 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1698 if (mimeType.empty()) {
1699 LogError("No mimeType provided.");
1702 for (int i = 0; i < contentBlackListLenth; ++i)
1704 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1706 LogWarning("mimeType blacklisted");
1707 //throw SecurityException
1712 ViewLogic* This = static_cast<ViewLogic*>(data);
1713 LogDebug("Creating handlers dao");
1714 This->attachToCustomHandlersDao();
1715 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1716 CustomHandlerDB::CustomHandlerPtr handler =
1717 handlersDao.getContentHandler(customHandler->target,
1719 customHandler->base_url);
1720 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1721 LogDebug("Protocol already registered - nothing to do");
1723 LogDebug("Protocol handler not found");
1724 Wrt::Popup::PopupResponse response =
1725 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1726 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1727 CONTENT_HANDLER_ASK_TITLE,
1728 CONTENT_HANDLER_ASK_MSG,
1729 CONTENT_HANDLER_AKS_REMEMBER);
1730 saveUserResponse(response, customHandler);
1731 if (customHandler->user_decision == CustomHandlerDB::Declined)
1733 handlersDao.registerContentHandler(*(customHandler.get()));
1734 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1735 //TODO remove old default handler somehow from appsvc
1736 LogDebug("Registering appservice entry");
1737 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1738 DPL::ToUTF8String(customHandler->target).c_str(),
1740 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1741 if (APPSVC_RET_OK != ret)
1743 LogWarning("Appsvc entry failed: " << ret);
1746 LogDebug("Content saved");
1748 This->detachFromCustomHandlersDao();
1751 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1756 CustomHandlerDB::CustomHandlerPtr customHandler =
1757 getCustomHandlerFromData(eventInfo);
1758 ViewLogic* This = static_cast<ViewLogic*>(data);
1759 LogDebug("Creating handlers dao");
1761 This->attachToCustomHandlersDao();
1762 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1763 CustomHandlerDB::CustomHandlerPtr handler =
1764 handlersDao.getContentHandler(customHandler->target,
1766 customHandler->base_url);
1768 if (handler->user_decision & CustomHandlerDB::Agreed)
1769 ewk_custom_handlers_data_result_set(
1770 static_cast<Ewk_Custom_Handlers_Data*>(data),
1771 EWK_CUSTOM_HANDLERS_REGISTERED);
1773 ewk_custom_handlers_data_result_set(
1774 static_cast<Ewk_Custom_Handlers_Data*>(data),
1775 EWK_CUSTOM_HANDLERS_DECLINED);
1777 ewk_custom_handlers_data_result_set(
1778 static_cast<Ewk_Custom_Handlers_Data*>(data),
1779 EWK_CUSTOM_HANDLERS_NEW);
1780 This->detachFromCustomHandlersDao();
1783 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1788 CustomHandlerDB::CustomHandlerPtr customHandler =
1789 getCustomHandlerFromData(eventInfo);
1790 ViewLogic* This = static_cast<ViewLogic*>(data);
1791 LogDebug("Creating handlers dao");
1792 This->attachToCustomHandlersDao();
1793 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1794 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1795 handlersDao.getContentHandler(customHandler->target,
1797 customHandler->base_url);
1799 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1800 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1802 handlersDao.unregisterContentHandler(customHandler->target,
1804 customHandler->base_url);
1806 LogDebug("Nothing to unregister");
1807 This->detachFromCustomHandlersDao();
1810 void ViewLogic::didRunJavaScriptCallback(
1811 Evas_Object* /*obj*/,
1815 LogInfo("didRunJavaScriptCallback called");
1816 LogInfo("result = " << result);
1819 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1821 LogDebug("closeIdlerCallback");
1822 ViewLogic* This = static_cast<ViewLogic*>(data);
1823 This->windowClose();
1824 return ECORE_CALLBACK_CANCEL;
1827 int ViewLogic::appcoreLowMemoryCallback(void *data)
1829 LogInfo("appcoreLowMemoryCallback");
1831 ViewLogic* This = static_cast<ViewLogic*>(data);
1833 if (NULL == This->m_ewkContext) {
1834 LogInfo("ewk isn't initialize at this moment");
1836 // Crash may occur on specific situation
1837 // So use the followings after they become stable
1838 //ewk_context_cache_clear(This->m_ewkContext);
1839 //ewk_context_notify_low_memory(This->m_ewkContext);
1845 void ViewLogic::databaseUsagePermissionRequestCallback(
1847 Evas_Object* /*obj*/,
1850 LogDebug("databaseUsagePermissionRequestCallback called");
1852 ViewLogic* This = static_cast<ViewLogic*>(data);
1855 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1856 SecurityOriginDB::FEATURE_WEB_DATABASE)
1857 == WrtDB::SETTINGS_TYPE_OFF)
1859 // default value is deny
1862 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1864 This->m_securityOriginSupport->getSecurityOriginDAO(),
1869 void ViewLogic::fileSystemPermissionRequestCallback(
1871 Evas_Object* /*obj*/,
1874 LogDebug("fileSystemPermissionRequestCallback called");
1876 ViewLogic* This = static_cast<ViewLogic*>(data);
1878 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1879 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
1880 == WrtDB::SETTINGS_TYPE_OFF)
1882 Ewk_Context_File_System_Permission* fileSystemPermission =
1883 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
1884 ewk_context_file_system_permission_allow_set(fileSystemPermission,
1890 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1892 This->m_securityOriginSupport->getSecurityOriginDAO(),
1896 void ViewLogic::didRecieveMessageFromInjectedBundle(
1898 const char* /*body*/)
1900 LogDebug("did recive message " << name);
1903 void ViewLogic::didReceiveSynchronousMessage(
1908 LogDebug("didReceiveSynchronousMessage called");
1913 LogDebug("body is empty");
1917 if (!strcmp(name, uriBlockedMessageName)) {
1918 LogDebug("received : " << uriBlockedMessageName);
1919 // Currently WebProcess informs obly about blocked
1920 // URI - URI localization and security chekcs are
1921 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
1922 // and bundle_uri_handling.cpp)
1923 rememberBlockedURI(DPL::FromUTF8String(body));
1925 } else if (!strcmp(name, uriChangedMessageName)) {
1926 LogDebug("received : " << uriChangedMessageName);
1927 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
1928 *returnData = strdup(ret.c_str());
1932 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
1934 m_blockedUri = DPL::ToUTF8String(inputURI);
1935 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
1939 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
1941 using namespace ViewModule::SecuritySupport;
1943 std::string url = DPL::ToUTF8String(changedURL);
1944 LogInfo("URL = [" << url << "]");
1947 // If url is same to URICHANGE_BLOCKED_URL,
1948 // this url has been already blocked by willsend.
1949 // So current page should be moved to previous page
1950 if (url == URICHANGE_BLOCKED_URL)
1952 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
1954 // block this page and open it in browser
1955 LogDebug("Request was blocked by WARP: " << url.c_str());
1956 if (!m_blockedUri.empty()) {
1957 LogDebug("open browser : " << m_blockedUri);
1958 bundle* bundleData = bundle_create();
1959 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
1960 appsvc_set_uri(bundleData, m_blockedUri.c_str());
1961 CONTROLLER_POST_EVENT(
1962 ApplicationLauncher,
1963 ApplicationLauncherEvents::LaunchApplicationByAppService(
1967 m_blockedUri = std::string();
1970 if (ewk_view_back_possible(m_currentEwkView)) {
1971 // go back to previous page
1972 ewk_view_back(m_currentEwkView);
1974 // stop current page
1975 ewk_view_stop(m_currentEwkView);
1976 ecore_idler_add(windowCloseIdlerCallback, this);
1979 // This is used in case of returning previous page
1981 return URICHANGE_PLUGIN_NO_CHANGE;
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(url.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(url.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 // register javascript object for plugins to be used
2012 LogInfo("Register Plugin Objects");
2013 return URICHANGE_PLUGIN_RESTART;
2016 void ViewLogic::windowClose()
2018 LogDebug("windowClose");
2019 Assert(m_closedEwkView && "no closed webview");
2021 if (1 >= m_ewkViewList.size()) {
2022 if (!m_cbs->webkitExit.empty()) {
2023 m_cbs->webkitExit();
2026 // call user callbacks
2027 if (!m_cbs->bufferUnset.empty()) {
2028 m_cbs->bufferUnset(m_currentEwkView);
2030 if (!m_cbs->windowClose.empty()) {
2031 m_cbs->windowClose(m_closedEwkView);
2033 removeEwkView(m_closedEwkView);
2035 // get latest ewkView
2036 m_currentEwkView = m_ewkViewList.back();
2037 const char* uri = ewk_view_url_get(m_currentEwkView);
2038 if (NULL == uri || 0 == strlen(uri)) {
2039 m_currentUri.clear();
2045 /* In case we support many pages in parallel
2046 then view is not suspended*/
2047 //resumeEwkView(m_currentEwkView);
2050 if (!m_cbs->bufferSet.empty()) {
2051 m_cbs->bufferSet(m_currentEwkView);