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::suspendWidget()
267 LogInfo("Pausing widget");
270 LogDebug("Request bundle to suspend");
271 PluginModuleSupport::suspend(m_ewkContext);
273 if (!m_currentEwkView) {
274 LogWarning("Cannot suspend widget without view");
276 suspendWebkit(m_currentEwkView);
279 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
281 // call user callback
282 if (!m_cbs->suspend.empty()) {
283 m_cbs->suspend(true);
287 void ViewLogic::resumeWidget()
289 LogInfo("Resume widget");
292 LogDebug("Request bundle to resume");
293 PluginModuleSupport::resume(m_ewkContext);
295 if (m_currentEwkView) {
296 resumeWebkit(m_currentEwkView);
299 /* window system team recomend removing this win_raise code. */
302 elm_win_raise(m_window);
305 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
307 // call user callback
308 if (!m_cbs->resume.empty()) {
313 void ViewLogic::resetWidget()
315 LogInfo("Resetting Widget");
317 // check if already created webview exists
318 if (!m_ewkViewList.size()) {
319 // create new webview
320 createEwkView(evas_object_evas_get(m_window));
322 ewkClientInit(m_currentEwkView);
323 prepareEwkView(m_currentEwkView);
325 // check if current url is service url for this tizen service
326 std::string requestedUri =
327 ViewModule::UriSupport::getUri(m_model, m_startUrl);
328 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
329 DPL::FromUTF8String(requestedUri.c_str()),
332 const char* currentUri = ewk_view_url_get(m_currentEwkView);
333 if (!currentUri && 0 == strlen(currentUri)) {
334 LogError("Fail to get uri from ewk_view_url_get");
339 PluginModuleSupport::resume(m_ewkContext);
340 resumeWebkit(m_currentEwkView);
341 if (DPL::ToUTF8String(*servicedUri) == currentUri) {
342 LogInfo("current page is raised");
343 // set only encoded bundle
344 double scale = elm_config_scale_get();
345 PluginModuleSupport::setCustomProperties(
348 ApplicationDataSingleton::Instance().getEncodedBundle());
349 PluginModuleSupport::dispatchJavaScriptEvent(
351 WrtPlugins::W3C::ServiceCustomEvent,
354 LogInfo("service page is loaded");
355 m_currentUri = DPL::ToUTF8String(*servicedUri);
356 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
358 elm_win_activate(m_window);
359 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
362 // call user callback
363 if (!m_cbs->reset.empty()) {
366 if (!m_cbs->bufferSet.empty()) {
367 m_cbs->bufferSet(m_currentEwkView);
371 void ViewLogic::backward()
373 if (ewk_view_back_possible(m_currentEwkView)) {
374 ewk_view_back(m_currentEwkView);
376 if (1 >= m_ewkViewList.size()) {
377 // If there is no previous page, widget move to backgroud.
378 LogInfo("Widget move to backgroud");
379 elm_win_lower(m_window);
381 // Back to previous webview
382 LogInfo("Widget move to previous webview");
383 ecore_idler_add(windowCloseIdlerCallback, this);
388 void ViewLogic::reloadStartPage()
390 LogInfo("Reload Start Page");
391 // prevent fail to load plugin bundle side
392 m_isBackgroundReload = true;
393 PluginModuleSupport::resume(m_ewkContext);
395 if (m_ewkViewList.size() != 0) {
396 while (m_ewkViewList.size() > 0) {
397 if (!m_cbs->bufferUnset.empty()) {
398 m_cbs->bufferUnset(m_currentEwkView);
400 removeEwkView(m_currentEwkView);
404 // create new webview
405 createEwkView(evas_object_evas_get(m_window));
406 ewkClientInit(m_currentEwkView);
409 prepareEwkView(m_currentEwkView);
410 initializePluginLoading();
413 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
416 if (!m_cbs->bufferSet.empty()) {
417 m_cbs->bufferSet(m_currentEwkView);
419 LogInfo("Reloading Start Page is done!");
422 Evas_Object* ViewLogic::getCurrentWebview()
424 LogInfo("get current webview");
425 return m_currentEwkView;
428 void ViewLogic::fireJavascriptEvent(int event, void* data)
430 PluginModuleSupport::dispatchJavaScriptEvent(
432 static_cast<WrtPlugins::W3C::CustomEventType>(event),
436 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
441 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
443 LogInfo("initializeEwkContext called");
444 Assert(newEwkContext && "Ewk_Context provided can not be null");
445 // bundle callback setting
446 ewk_context_message_from_injected_bundle_callback_set(
448 contextMessageFromInjectedBundleCallback,
449 static_cast<void*>(this));
451 // proxy server setting
452 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
453 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
454 || (strstr(proxyAddress, "0.0.0.0")))
456 LogInfo("proxy address is empty");
457 ewk_context_proxy_uri_set(newEwkContext, NULL);
459 LogInfo("proxy address [" << proxyAddress << "]");
460 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
469 const char *theme = elm_theme_get(NULL);
472 LogInfo("theme is " << m_theme);
475 // Ewk download callback (WKContextDownloadClient)
476 ewk_context_did_start_download_callback_set(
478 didStartDownloadCallback,
481 // set to member value
482 m_ewkContext = newEwkContext;
485 void ViewLogic::finalizeEwkContext()
487 LogInfo("finalizeEwkContext called");
488 ewk_context_message_from_injected_bundle_callback_set(
492 // ewk_context_delete(m_ewkContext);
496 void ViewLogic::initializeSupport()
498 // set local stroage database path
499 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
500 ewk_context_web_storage_path_set(m_ewkContext,
501 dao.getPrivateLocalStoragePath().c_str());
502 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
503 ViewModule::StorageSupport::initializeStorage(m_model);
504 m_appsSupport->initialize(m_model);
505 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
507 m_vibrationSupport->initialize();
510 void ViewLogic::initializePluginLoading()
512 // inform wrt information for plugin loading to web process
513 PluginModuleSupport::start(
516 elm_config_scale_get(),
517 ApplicationDataSingleton::Instance().getEncodedBundle(),
519 m_model->SettingList.Get().isEncrypted());
522 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
523 Assert(NULL != wkView && "ewk_view not created at this point");
525 FOREACH(it, m_ewkCallbacksMap) {
526 evas_object_smart_callback_add(
534 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
535 LogDebug("ewkClientDeinit");
536 Assert(NULL != wkView && "ewk_view not created at this point");
538 FOREACH(it, m_ewkCallbacksMap) {
539 evas_object_smart_callback_del(
546 void ViewLogic::createEwkView(Evas* canvas)
548 LogDebug("createEwkVeiw");
550 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
551 Evas_Object* newEwkView = ewk_view_add_with_context(
554 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
557 LogError("WKView creation failed");
562 // even arguments pass the ewkContext, this API should be called
563 // after webkit Evas_Object is created
564 Ewk_Cookie_Manager *ewkCookieManager;
566 ewk_context_cookie_manager_get(m_ewkContext);
567 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
568 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
570 LogInfo("push webview: " << newEwkView);
571 m_ewkViewList.push_back(newEwkView);
572 m_currentEwkView = newEwkView;
575 void ViewLogic::setStartPage()
577 /* Start URI (as other uris) is now localized
578 * on WebProcess side */
579 m_currentUri = m_startUrl;
582 void ViewLogic::prepareEwkView(Evas_Object *wkView)
584 LogDebug("prepareEwkView called");
586 Ewk_Settings* settings = ewk_view_settings_get(wkView);
589 std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
590 if (customUserAgent.empty()) {
591 auto userAgentString =
592 ViewModule::UserAgentSupport::getUserAgentFromVconf();
593 if (!userAgentString.empty()) {
594 LogDebug("Setting user agent as: " << userAgentString);
595 ewk_view_user_agent_set(wkView, userAgentString.c_str());
598 LogDebug("Setting custom user agent as: " << customUserAgent);
599 ewk_view_user_agent_set(wkView, customUserAgent.c_str());
602 // set custom header : language
603 using namespace ViewModule::CustomHeaderSupport;
604 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
605 if (!customHeaderString.empty()) {
606 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
607 LogDebug("custom value=[" << customHeaderString << "]");
608 ewk_view_custom_header_add(wkView,
609 ACCEPT_LANGUAGE.c_str(),
610 customHeaderString.c_str());
613 // webkit NPAPI plugins is always on in wrt
614 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
616 // The followings are not implemeted yet by webkit2
617 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
618 // ewk_view_mode_set();
619 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
620 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
621 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
622 // elm_webview_show_magnifier_set(EINA_FALSE);
623 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
624 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
625 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
627 // disable zoom option when user click the input field
628 // this option is useful with the normal website
629 // for the make user friendly, disable auto zoom in the webapp
630 // The followings are not implemeted yet by webkit2
631 // elm_webview_input_field_zoom_set(EINA_FALSE);
633 // set cookie database path
634 // The followings are not implemeted yet by webkit2
635 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
637 // set visibility to WebCore. This value will be used for html5.
638 // also, this value will be changed in the suspend, resume
639 // or create window, close window.
640 ewk_view_page_visibility_state_set(wkView,
641 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
645 void ViewLogic::removeEwkView(Evas_Object *wkView)
647 LogInfo("removeEwkView called");
649 Assert(0 != m_ewkViewList.size());
651 // unregister webview callbacks
652 ewkClientDeinit(wkView);
654 // suspend NPAPI plugin - Not implemented by Webkit2
655 // ewk_view_pause_or_resume_plugins();
656 evas_object_del(wkView);
657 m_ewkViewList.remove(wkView);
660 void ViewLogic::resumeEwkView(Evas_Object *wkView)
662 LogInfo("resumeEwkView called");
665 // register webview callback
666 ewkClientInit(wkView);
669 resumeWebkit(wkView);
674 void ViewLogic::suspendEwkView(Evas_Object *wkView)
676 LogInfo("suspendEwkView called");
680 suspendWebkit(wkView);
682 // unregister webview callbacks
683 ewkClientDeinit(wkView);
688 void ViewLogic::resumeWebkit(Evas_Object *wkView)
690 LogDebug("resumeWebkit");
693 // resume NPAPI plugin
694 // The followings are not implemeted yet by webkit2
695 // ewk_view_pause_or_resume_plugins(false);
696 // ewk_view_pause_or_resume_video_audio(false);
697 // ewk_view_javascript_resume();
698 // ewk_view_enable_render();
699 // ewk_view_reduce_plugins_frame_rate(false);
700 ewk_view_resume(wkView);
701 ewk_view_visibility_set(wkView, EINA_TRUE);
702 ewk_view_page_visibility_state_set(wkView,
703 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
708 void ViewLogic::suspendWebkit(Evas_Object *wkView)
710 LogDebug("suspendWebkit");
713 // suspend the followings
714 // The followings are not implemeted yet by webkit2
715 // ewk_view_pause_or_resume_plugins(true);
716 // ewk_view_pause_or_resume_video_audio(true);
718 // send visibility event to webpage
719 ewk_view_page_visibility_state_set(wkView,
720 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
722 ewk_view_suspend(wkView);
723 ewk_view_visibility_set(wkView, EINA_FALSE);
727 void ViewLogic::contextMessageFromInjectedBundleCallback(
733 LogDebug("contextMessageFromInjectedBundleCallback called");
735 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
736 // didRecieveMessageFromInjectedBundleCallback - returnData is null
737 // didReceiveSynchronousMessageCallback - returnData isn't null
738 // WKContextInjectedBundleClient bundleClient = {
739 // kWKContextInjectedBundleClientCurrentVersion,
740 // static_cast<void*>(this),
741 // &didRecieveMessageFromInjectedBundleCallback,
742 // &didReceiveSynchronousMessageCallback
744 if (NULL == returnData) {
745 This->didRecieveMessageFromInjectedBundle(name, body);
747 This->didReceiveSynchronousMessage(name, body, returnData);
751 void ViewLogic::didStartDownloadCallback(
752 const char* downloadUrl,
755 LogDebug("didStartDownloadCallback called");
757 ViewLogic* This = static_cast<ViewLogic*>(data);
759 LogDebug("download url = " << downloadUrl);
760 This->m_appsSupport->downloadRequest(
766 void ViewLogic::loadStartedCallback(
771 LogDebug("loadStartedCallback called");
773 ViewLogic* This = static_cast<ViewLogic*>(data);
774 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
776 // call loadFinish callback to wrt-client
777 if (!This->m_cbs->loadStart.empty()) {
778 This->m_cbs->loadStart(obj);
783 void ViewLogic::loadFinishedCallback(
788 LogDebug("loadFinishedCallback called");
790 ViewLogic* This = static_cast<ViewLogic*>(data);
793 const char* url = ewk_view_url_get(This->m_currentEwkView);
794 if (NULL == url || strlen(url) == 0) {
795 LogError("url is empty");
797 DPL::OptionalString jsOptionalString =
798 ViewModule::PasswordSupport::jsForAutoFillData(url);
799 if (jsOptionalString.IsNull()) {
800 LogError("Fail to get JS String");
802 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
804 if(EINA_FALSE == ewk_view_script_execute(
805 This->m_currentEwkView,
807 didRunJavaScriptCallback,
810 LogError("JS for auto fill data failed.");
815 // call loadFinish callback to wrt-client
816 if (!This->m_cbs->loadFinish.empty()) {
817 This->m_cbs->loadFinish(obj);
820 // set only encoded bundle
821 double scale = elm_config_scale_get();
822 PluginModuleSupport::setCustomProperties(
825 ApplicationDataSingleton::Instance().getEncodedBundle());
826 // check if 'appsevice' event is registed at the current frames.
827 // If so, dispatch the event to frames.
828 PluginModuleSupport::dispatchJavaScriptEvent(
830 WrtPlugins::W3C::ServiceCustomEvent,
833 // In this case, widget is reloaded in the background.
834 // After finished load, bundle should disconnent callback.
835 if (This->m_isBackgroundReload) {
836 PluginModuleSupport::suspend(This->m_ewkContext);
837 ewk_view_suspend(This->m_currentEwkView);
838 This->m_isBackgroundReload = false;
842 void ViewLogic::titleChangedCallback(
844 Evas_Object* /*obj*/,
847 LogDebug("titleChangedCallback called");
849 ViewLogic* This = static_cast<ViewLogic*>(data);
851 const char* title = static_cast<char*>(eventInfo);
853 if (0 == strlen(title)) {
854 LogDebug("title data is empty");
857 LogDebug("Title = [" << title << "]");
858 This->m_schemeSupport->HandleTizenScheme(title,
860 This->m_currentEwkView);
863 void ViewLogic::loadProgressCallback(
865 Evas_Object* /*obj*/,
868 double* progress = static_cast<double*>(eventInfo);
869 LogDebug("didChangeProgressCallback progress = " << *progress);
872 void ViewLogic::loadProgressFinishedCallback(
874 Evas_Object* /*obj*/,
877 LogDebug("didFinishProgressCallback");
879 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
880 if (!view->m_cbs->progressFinish.empty()) {
881 view->m_cbs->progressFinish();
885 void ViewLogic::processCrashedCallback(
887 Evas_Object* /*obj*/,
890 LogInfo("processCrashedCallback");
892 ViewLogic const * const view =
893 static_cast<ViewLogic const * const>(data);
894 if (!view->m_cbs->webCrash.empty()) {
895 view->m_cbs->webCrash();
897 // This flag will be prevented exit() call in the Webkit side
898 if (NULL != eventInfo) {
899 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
903 void ViewLogic::createWindowCallback(
908 LogDebug("createWindowCallback");
910 ViewLogic* This = static_cast<ViewLogic*>(data);
912 // First, current webview should be handled by user callback
913 if (!This->m_cbs->bufferUnset.empty()) {
914 This->m_cbs->bufferUnset(obj);
917 // this can be set by executable for specific purpose
919 if (!This->m_cbs->windowCreateBefore.empty()) {
920 // 'obj' is parent webview object
921 This->m_cbs->windowCreateBefore(&canvas, obj);
924 canvas = evas_object_evas_get(This->m_window);
927 // create new ewkview
928 This->createEwkView(canvas);
929 Evas_Object* newEwkView = This->m_currentEwkView;
931 // initialize new ewkview
932 This->setStartPage();
933 This->ewkClientInit(newEwkView);
934 This->prepareEwkView(newEwkView);
936 // Specific jobs of child, parent webview are handled by each executable
937 if (!This->m_cbs->windowCreateAfter.empty()) {
938 // 'obj' is parent webview, 'newEwkView' is child webview
939 This->m_cbs->windowCreateAfter(obj, newEwkView);
942 // Lastly, new webview should be handled by user callback
943 if (!This->m_cbs->bufferSet.empty()) {
944 This->m_cbs->bufferSet(newEwkView);
946 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
949 void ViewLogic::closeWindowCallback(
954 LogDebug("closeWindowCallback");
955 ViewLogic* This = static_cast<ViewLogic*>(data);
956 This->m_closedEwkView = obj;
957 ecore_idler_add(windowCloseIdlerCallback, This);
960 void ViewLogic::policyNavigationDecideCallback(
962 Evas_Object* /*obj*/,
965 LogDebug("policyNavigationDecideCallback called");
967 ViewLogic* This = static_cast<ViewLogic*>(data);
969 Ewk_Policy_Decision* policyDecision =
970 static_cast<Ewk_Policy_Decision*>(eventInfo);
972 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
976 This->m_currentEwkView))
979 ewk_policy_decision_use(policyDecision);
981 // check whether this is new empty window
982 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
983 if(!activeUrl || 0 == strlen(activeUrl)) {
985 * The view is empty and scheme has been handled externally. When
986 * user gets back from the external application he'd see blank page
987 * and won't be able to navigate back. This happens when window.open
988 * is used to handle schemes like sms/mms/mailto (for example in
989 * WAC web standards tests: WS-15XX).
991 * To solve the problem, the empty view is removed from the stack
992 * and the previous one is shown. This is not an elegant solution
993 * but we don't have a better one.
995 LogInfo("Scheme has been handled externally. Removing empty view.");
996 if (ewk_view_back_possible(This->m_currentEwkView)) {
997 // go back to previous WKPage
998 ewk_view_back(This->m_currentEwkView);
1000 // stop current WKPage
1001 ewk_view_stop(This->m_currentEwkView);
1002 ecore_idler_add(windowCloseIdlerCallback, This);
1007 ewk_policy_decision_ignore(policyDecision);
1011 void ViewLogic::policyNewWindowDecideCallback(
1013 Evas_Object* /*obj*/,
1016 LogDebug("policyNewWindowDecideCallback called");
1018 ViewLogic* This = static_cast<ViewLogic*>(data);
1020 Ewk_Policy_Decision* policyDecision =
1021 static_cast<Ewk_Policy_Decision*>(eventInfo);
1023 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1027 This->m_currentEwkView))
1029 ewk_policy_decision_use(policyDecision);
1032 ewk_policy_decision_ignore(policyDecision);
1036 void ViewLogic::pageResponseDecideCallback(
1038 Evas_Object* /*obj*/,
1041 LogDebug("pageResponseDecideCallback called");
1043 ViewLogic* This = static_cast<ViewLogic*>(data);
1045 Ewk_Policy_Decision* policyDecision =
1046 static_cast<Ewk_Policy_Decision*>(eventInfo);
1047 Ewk_Policy_Decision_Type policyDecisionType =
1048 ewk_policy_decision_type_get(policyDecision);
1050 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1052 ewk_policy_decision_use(policyDecision);
1053 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1054 LogDebug("download");
1055 ewk_policy_decision_suspend(policyDecision);
1057 // get uri information
1058 const char* url = ewk_policy_decision_url_get(policyDecision);
1059 if (NULL == url || strlen(url) == 0) {
1060 LogDebug("url data is empty");
1061 ewk_policy_decision_use(policyDecision);
1064 LogDebug("url = [" << url << "]");
1066 // get content information
1067 const char* content =
1068 ewk_policy_decision_response_mime_get(policyDecision);
1069 LogDebug("content type = [" << content << "]");
1071 // get cookie information
1072 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1073 LogDebug("cookie = [" << cookie << "]");
1075 LogDebug("Content not supported, will be opened in external app");
1076 This->m_appsSupport->downloadRequest(
1080 ewk_policy_decision_ignore(policyDecision);
1081 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1083 ewk_policy_decision_ignore(policyDecision);
1085 LogDebug("Type isn't handled");
1086 ewk_policy_decision_ignore(policyDecision);
1090 void ViewLogic::contextmenuCustomizeCallback(
1092 Evas_Object* /*obj*/,
1095 LogDebug("contextmenuCustomizeCallback called");
1098 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1099 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1100 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1101 (This->m_model->SettingList.Get().getContextMenu()
1102 == ContextMenu_Disable))
1104 LogDebug("ContextMenu Disable!!");
1105 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1106 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1108 ewk_context_menu_item_remove(menu, item);
1111 LogDebug("ContextMenu Enable!!");
1112 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1113 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1115 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1118 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1119 ewk_context_menu_item_remove(menu, item);
1122 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1123 ewk_context_menu_item_remove(menu, item);
1134 void ViewLogic::formSubmitCallback(
1136 Evas_Object* /*obj*/,
1139 LogDebug("formSubmitCallback called");
1141 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1143 const char* uri = ewk_form_data_url_get(formData);
1145 LogError("URL is empty");
1149 Eina_Hash* userData = ewk_form_data_values_get(formData);
1150 ViewModule::PasswordSupport::submitClicked(uri, userData);
1153 void ViewLogic::geolocationPermissionRequestCallback(
1155 Evas_Object* /*obj*/,
1159 ViewLogic* This = static_cast<ViewLogic*>(data);
1161 Ewk_Geolocation_Permission_Data* permissionRequest =
1162 static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1164 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1165 SecurityOriginDB::FEATURE_GEOLOCATION)
1166 == WrtDB::SETTINGS_TYPE_OFF)
1168 ewk_geolocation_permission_request_allow_set(
1169 ewk_geolocation_permission_request_get(permissionRequest),
1173 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1175 This->m_securityOriginSupport->getSecurityOriginDAO(),
1179 void ViewLogic::notificationShowCallback(
1181 Evas_Object* /*obj*/,
1184 LogDebug("notificationShowCallback called");
1186 ViewLogic* This = static_cast<ViewLogic*>(data);
1189 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1191 using namespace ViewModule::WebNotification;
1193 WebNotificationDataPtr notiData(
1194 new WebNotificationData(
1196 ewk_notification_id_get(noti)));
1198 DPL::OptionalString string =
1199 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1200 if (!string.IsNull()) {
1201 notiData->m_iconURL = DPL::ToUTF8String(*string);
1203 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1204 if (!string.IsNull()) {
1205 notiData->m_title = DPL::ToUTF8String(*string);
1207 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1208 if (!string.IsNull()) {
1209 notiData->m_body = DPL::ToUTF8String(*string);
1212 LogInfo("notification id : " << notiData->m_id);
1213 LogInfo("notification iconURL : " << notiData->m_iconURL);
1214 LogInfo("notification title : " << notiData->m_title);
1215 LogInfo("notification body : " << notiData->m_body);
1217 showWebNotification(notiData);
1218 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1221 void ViewLogic::notificationCancelCallback(
1223 Evas_Object* /*obj*/,
1224 void* /*eventInfo*/)
1226 LogDebug("notificationCancelCallback called");
1229 void ViewLogic::notificationPermissionRequestCallback(
1231 Evas_Object* /*obj*/,
1234 LogDebug("notificationPermissionRequestCallback called");
1236 ViewLogic* This = static_cast<ViewLogic*>(data);
1237 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1238 SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1239 == WrtDB::SETTINGS_TYPE_OFF)
1241 Ewk_Notification_Permission_Request* request =
1242 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1243 ewk_notification_permission_request_response(
1251 ViewModule::WebNotification::webNotificationPermissionRequest(
1253 This->m_securityOriginSupport->getSecurityOriginDAO(),
1259 void ViewLogic::vibrationVibrateCallback(
1261 Evas_Object* /*obj*/,
1264 LogDebug("vibrationVibrateCallback called");
1266 ViewLogic* This = static_cast<ViewLogic*>(data);
1269 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1271 This->m_vibrationSupport->startVibration(vibrationTime);
1276 void ViewLogic::vibrationCancelCallback(
1278 Evas_Object* /*obj*/,
1279 void* /*eventInfo*/)
1281 LogDebug("vibrationCancelCallback called");
1283 ViewLogic* This = static_cast<ViewLogic*>(data);
1285 This->m_vibrationSupport->stopVibration();
1290 // EWK Orientation Callback
1291 Eina_Bool ViewLogic::orientationLockCallback(
1293 Eina_Bool /*needLock*/,
1297 LogDebug("orientationLockCallback called");
1299 ViewLogic* This = static_cast<ViewLogic*>(data);
1301 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1302 LogDebug("orientation is portrait-primary");
1303 elm_win_rotation_with_resize_set(This->m_window, 0);
1304 ewk_view_orientation_send(obj, 0);
1305 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1306 LogDebug("orientation is landscape-primary");
1307 elm_win_rotation_with_resize_set(This->m_window, 270);
1308 ewk_view_orientation_send(obj, 90);
1309 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1310 LogDebug("orientation is portrait-secondary");
1311 elm_win_rotation_with_resize_set(This->m_window, 180);
1312 ewk_view_orientation_send(obj, 180);
1313 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1314 LogDebug("orientation is landscape-secondary");
1315 elm_win_rotation_with_resize_set(This->m_window, 90);
1316 ewk_view_orientation_send(obj, -90);
1318 LogDebug("Wrong orientation is set");
1325 // Fullscreen API callbacks
1326 void ViewLogic::enterFullscreenCallback(
1328 Evas_Object* /*obj*/,
1329 void* /*eventInfo*/)
1331 LogInfo("enterFullscreenCallback called");
1333 ViewLogic* This = static_cast<ViewLogic*>(data);
1334 if (!This->m_cbs->toggleFullscreen.empty()) {
1335 This->m_cbs->toggleFullscreen(true);
1338 void ViewLogic::exitFullscreenCallback(
1340 Evas_Object* /*obj*/,
1341 void* /*eventInfo*/)
1343 LogInfo("exitFullscreenCallback called");
1345 ViewLogic* This = static_cast<ViewLogic*>(data);
1346 if (!This->m_cbs->toggleFullscreen.empty()) {
1347 This->m_cbs->toggleFullscreen(false);
1351 void ViewLogic::imeChangedCallback(
1353 Evas_Object* /*obj*/,
1359 ViewLogic* This = static_cast<ViewLogic*>(data);
1360 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1361 This->m_imeWidth = rect->w;
1362 This->m_imeHeight = rect->h;
1365 void ViewLogic::imeOpenedCallback(
1367 Evas_Object* /*obj*/,
1368 void* /*eventInfo*/)
1372 ViewLogic* This = static_cast<ViewLogic*>(data);
1374 using namespace WrtPlugins::W3C;
1375 SoftKeyboardChangeArgs args;
1376 args.state = IME_STATE_ON;
1377 args.width = This->m_imeWidth;
1378 args.height = This->m_imeHeight;
1379 This->fireJavascriptEvent(
1380 static_cast<int>(SoftKeyboardChangeCustomEvent),
1384 void ViewLogic::imeClosedCallback(
1386 Evas_Object* /*obj*/,
1387 void* /*eventInfo*/)
1391 ViewLogic* This = static_cast<ViewLogic*>(data);
1393 using namespace WrtPlugins::W3C;
1394 SoftKeyboardChangeArgs args;
1395 args.state = IME_STATE_OFF;
1397 This->fireJavascriptEvent(
1398 static_cast<int>(SoftKeyboardChangeCustomEvent),
1402 void ViewLogic::usermediaPermissionRequestCallback(
1404 Evas_Object* /*obj*/,
1407 LogDebug("usermediaPermissionRequestCallback called");
1409 ViewLogic* This = static_cast<ViewLogic*>(data);
1410 ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1416 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1419 Ewk_Custom_Handlers_Data* handler =
1420 static_cast<Ewk_Custom_Handlers_Data*>(data);
1421 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1422 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1424 LogDebug("base url: " << base_url);
1425 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1427 const char* url = ewk_custom_handlers_data_url_get(handler);
1429 LogDebug("url: " << url);
1430 customHandler->url = DPL::FromASCIIString(string(url));
1432 const char* target = ewk_custom_handlers_data_target_get(handler);
1434 LogDebug("target: " << target);
1435 customHandler->target = DPL::FromASCIIString(string(target));
1437 const char* title = ewk_custom_handlers_data_title_get(handler);
1439 LogDebug("title: " << title);
1440 customHandler->title = DPL::FromASCIIString(string(title));
1442 return customHandler;
1445 void ViewLogic::attachToCustomHandlersDao()
1447 if (!m_attachedToCustomHandlerDao) {
1448 CustomHandlerDB::Interface::attachDatabaseRW();
1452 void ViewLogic::detachFromCustomHandlersDao()
1454 if (m_attachedToCustomHandlerDao) {
1455 CustomHandlerDB::Interface::detachDatabase();
1459 const int protocolWhiteListLenth = 15;
1460 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1478 const int contentBlackListLenth = 14;
1479 char const * const contentBlackList[contentBlackListLenth] = {
1480 "application/x-www-form-urlencoded",
1481 "application/xhtml+xml",
1487 "multipart/x-mixed-replace",
1488 "text/cache-manifest",
1497 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1500 * @param customHandler
1502 void saveUserResponse(Wrt::Popup::PopupResponse response,
1503 CustomHandlerDB::CustomHandlerPtr customHandler)
1506 case Wrt::Popup::YES_DO_REMEMBER:
1507 LogDebug("User allowed, remember");
1508 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1509 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1511 case Wrt::Popup::YES_DONT_REMEMBER:
1512 LogDebug("User allowed, don't remember");
1513 customHandler->user_decision = CustomHandlerDB::Agreed;
1515 case Wrt::Popup::NO_DO_REMEMBER:
1516 LogDebug("User didn't allow, remember");
1517 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1518 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1520 case Wrt::Popup::NO_DONT_REMEMBER:
1521 LogDebug("User didn't allow, don't remember");
1522 customHandler->user_decision = CustomHandlerDB::Declined;
1527 //TODO registration, checking if registered and unregistration can be done in
1528 //common functions for both types of handlers. Only white and black lists
1529 //have to be separated
1530 //TODO attach database only one at the start (not in every callback?)
1531 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1537 CustomHandlerDB::CustomHandlerPtr customHandler =
1538 getCustomHandlerFromData(eventInfo);
1540 std::string scheme = DPL::ToUTF8String(customHandler->target);
1541 if (scheme.empty()) {
1542 LogError("No scheme provided");
1543 //TODO what about securityError?
1546 bool matched = false;
1547 //scheme on whiteList
1548 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1549 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1551 LogDebug("Match found, protocol can be handled");
1556 //starts with web+ and have at least 5 chars (lowercase ASCII)
1557 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1558 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1559 //throw SecurityException
1566 if (c < 'a' || c > 'z') {
1567 LogWarning("Wrong char inside scheme. "
1568 << "Only lowercase ASCII letters accepted");
1569 //throw SecurityException
1576 ViewLogic* This = static_cast<ViewLogic*>(data);
1577 LogDebug("Creating handlers dao");
1578 This->attachToCustomHandlersDao();
1579 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1580 CustomHandlerDB::CustomHandlerPtr handler =
1581 handlersDao.getProtocolHandler(customHandler->target,
1583 customHandler->base_url);
1584 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1585 LogDebug("Protocol already registered - nothing to do");
1587 LogDebug("Protocol handler not found");
1588 Wrt::Popup::PopupResponse response =
1589 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1590 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1591 PROTOCOL_HANDLER_ASK_TITLE,
1592 PROTOCOL_HANDLER_ASK_MSG,
1593 PROTOCOL_HANDLER_ASK_REMEMBER);
1594 saveUserResponse(response, customHandler);
1595 if (customHandler->user_decision == CustomHandlerDB::Declined)
1597 handlersDao.registerProtocolHandler(*(customHandler.get()));
1598 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1599 //TODO remove old default handler somehow from appsvc
1600 LogDebug("Registering appservice entry");
1601 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1603 DPL::ToUTF8String(customHandler->target).c_str(),
1604 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1605 if (APPSVC_RET_OK != ret)
1607 LogWarning("Appsvc entry failed: " << ret);
1610 LogDebug("Protocal saved");
1613 This->detachFromCustomHandlersDao();
1616 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1621 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1622 ViewLogic* This = static_cast<ViewLogic*>(data);
1623 LogDebug("Creating handlers dao");
1624 This->attachToCustomHandlersDao();
1625 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1626 CustomHandlerDB::CustomHandlerPtr handler =
1627 handlersDao.getProtocolHandler(customHandler->target,
1629 customHandler->base_url);
1631 if (handler->user_decision & CustomHandlerDB::Agreed)
1632 ewk_custom_handlers_data_result_set(
1633 static_cast<Ewk_Custom_Handlers_Data*>(data),
1634 EWK_CUSTOM_HANDLERS_REGISTERED);
1636 ewk_custom_handlers_data_result_set(
1637 static_cast<Ewk_Custom_Handlers_Data*>(data),
1638 EWK_CUSTOM_HANDLERS_DECLINED);
1640 ewk_custom_handlers_data_result_set(
1641 static_cast<Ewk_Custom_Handlers_Data*>(data),
1642 EWK_CUSTOM_HANDLERS_NEW);
1643 This->detachFromCustomHandlersDao();
1646 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1651 CustomHandlerDB::CustomHandlerPtr customHandler =
1652 getCustomHandlerFromData(eventInfo);
1653 ViewLogic* This = static_cast<ViewLogic*>(data);
1654 LogDebug("Creating handlers dao");
1655 This->attachToCustomHandlersDao();
1656 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1657 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1658 handlersDao.getProtocolHandler(customHandler->target,
1660 customHandler->base_url);
1662 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1663 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1665 handlersDao.unregisterProtocolHandler(customHandler->target,
1667 customHandler->base_url);
1669 LogDebug("Nothing to unregister");
1671 This->detachFromCustomHandlersDao();
1674 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1680 CustomHandlerDB::CustomHandlerPtr customHandler =
1681 getCustomHandlerFromData(eventInfo);
1683 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1684 if (mimeType.empty()) {
1685 LogError("No mimeType provided.");
1688 for (int i = 0; i < contentBlackListLenth; ++i)
1690 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1692 LogWarning("mimeType blacklisted");
1693 //throw SecurityException
1698 ViewLogic* This = static_cast<ViewLogic*>(data);
1699 LogDebug("Creating handlers dao");
1700 This->attachToCustomHandlersDao();
1701 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1702 CustomHandlerDB::CustomHandlerPtr handler =
1703 handlersDao.getContentHandler(customHandler->target,
1705 customHandler->base_url);
1706 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1707 LogDebug("Protocol already registered - nothing to do");
1709 LogDebug("Protocol handler not found");
1710 Wrt::Popup::PopupResponse response =
1711 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1712 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1713 CONTENT_HANDLER_ASK_TITLE,
1714 CONTENT_HANDLER_ASK_MSG,
1715 CONTENT_HANDLER_AKS_REMEMBER);
1716 saveUserResponse(response, customHandler);
1717 if (customHandler->user_decision == CustomHandlerDB::Declined)
1719 handlersDao.registerContentHandler(*(customHandler.get()));
1720 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1721 //TODO remove old default handler somehow from appsvc
1722 LogDebug("Registering appservice entry");
1723 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1724 DPL::ToUTF8String(customHandler->target).c_str(),
1726 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1727 if (APPSVC_RET_OK != ret)
1729 LogWarning("Appsvc entry failed: " << ret);
1732 LogDebug("Content saved");
1734 This->detachFromCustomHandlersDao();
1737 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1742 CustomHandlerDB::CustomHandlerPtr customHandler =
1743 getCustomHandlerFromData(eventInfo);
1744 ViewLogic* This = static_cast<ViewLogic*>(data);
1745 LogDebug("Creating handlers dao");
1747 This->attachToCustomHandlersDao();
1748 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1749 CustomHandlerDB::CustomHandlerPtr handler =
1750 handlersDao.getContentHandler(customHandler->target,
1752 customHandler->base_url);
1754 if (handler->user_decision & CustomHandlerDB::Agreed)
1755 ewk_custom_handlers_data_result_set(
1756 static_cast<Ewk_Custom_Handlers_Data*>(data),
1757 EWK_CUSTOM_HANDLERS_REGISTERED);
1759 ewk_custom_handlers_data_result_set(
1760 static_cast<Ewk_Custom_Handlers_Data*>(data),
1761 EWK_CUSTOM_HANDLERS_DECLINED);
1763 ewk_custom_handlers_data_result_set(
1764 static_cast<Ewk_Custom_Handlers_Data*>(data),
1765 EWK_CUSTOM_HANDLERS_NEW);
1766 This->detachFromCustomHandlersDao();
1769 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1774 CustomHandlerDB::CustomHandlerPtr customHandler =
1775 getCustomHandlerFromData(eventInfo);
1776 ViewLogic* This = static_cast<ViewLogic*>(data);
1777 LogDebug("Creating handlers dao");
1778 This->attachToCustomHandlersDao();
1779 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1780 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1781 handlersDao.getContentHandler(customHandler->target,
1783 customHandler->base_url);
1785 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1786 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1788 handlersDao.unregisterContentHandler(customHandler->target,
1790 customHandler->base_url);
1792 LogDebug("Nothing to unregister");
1793 This->detachFromCustomHandlersDao();
1796 void ViewLogic::didRunJavaScriptCallback(
1797 Evas_Object* /*obj*/,
1801 LogInfo("didRunJavaScriptCallback called");
1802 LogInfo("result = " << result);
1805 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1807 LogDebug("closeIdlerCallback");
1808 ViewLogic* This = static_cast<ViewLogic*>(data);
1809 This->windowClose();
1810 return ECORE_CALLBACK_CANCEL;
1813 int ViewLogic::appcoreLowMemoryCallback(void *data)
1815 LogInfo("appcoreLowMemoryCallback");
1817 ViewLogic* This = static_cast<ViewLogic*>(data);
1819 if (NULL == This->m_ewkContext) {
1820 LogInfo("ewk isn't initialize at this moment");
1822 // Crash may occur on specific situation
1823 // So use the followings after they become stable
1824 //ewk_context_cache_clear(This->m_ewkContext);
1825 //ewk_context_notify_low_memory(This->m_ewkContext);
1831 void ViewLogic::databaseUsagePermissionRequestCallback(
1833 Evas_Object* /*obj*/,
1836 LogDebug("databaseUsagePermissionRequestCallback called");
1838 ViewLogic* This = static_cast<ViewLogic*>(data);
1841 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1842 SecurityOriginDB::FEATURE_WEB_DATABASE)
1843 == WrtDB::SETTINGS_TYPE_OFF)
1845 // default value is deny
1848 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1850 This->m_securityOriginSupport->getSecurityOriginDAO(),
1855 void ViewLogic::fileSystemPermissionRequestCallback(
1857 Evas_Object* /*obj*/,
1860 LogDebug("fileSystemPermissionRequestCallback called");
1862 ViewLogic* This = static_cast<ViewLogic*>(data);
1864 if (This->m_securityOriginSupport->isNeedPermissionCheck(
1865 SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
1866 == WrtDB::SETTINGS_TYPE_OFF)
1868 Ewk_Context_File_System_Permission* fileSystemPermission =
1869 static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
1870 ewk_context_file_system_permission_allow_set(fileSystemPermission,
1876 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1878 This->m_securityOriginSupport->getSecurityOriginDAO(),
1882 void ViewLogic::didRecieveMessageFromInjectedBundle(
1884 const char* /*body*/)
1886 LogDebug("did recive message " << name);
1889 void ViewLogic::didReceiveSynchronousMessage(
1894 LogDebug("didReceiveSynchronousMessage called");
1899 LogDebug("body is empty");
1903 if (!strcmp(name, uriBlockedMessageName)) {
1904 LogDebug("received : " << uriBlockedMessageName);
1905 // Currently WebProcess informs obly about blocked
1906 // URI - URI localization and security chekcs are
1907 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
1908 // and bundle_uri_handling.cpp)
1909 rememberBlockedURI(DPL::FromUTF8String(body));
1911 } else if (!strcmp(name, uriChangedMessageName)) {
1912 LogDebug("received : " << uriChangedMessageName);
1913 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
1914 *returnData = strdup(ret.c_str());
1918 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
1920 m_blockedUri = DPL::ToUTF8String(inputURI);
1921 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
1925 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
1927 using namespace ViewModule::SecuritySupport;
1929 std::string url = DPL::ToUTF8String(changedURL);
1930 LogInfo("URL = [" << url << "]");
1933 // If url is same to URICHANGE_BLOCKED_URL,
1934 // this url has been already blocked by willsend.
1935 // So current page should be moved to previous page
1936 if (url == URICHANGE_BLOCKED_URL)
1938 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
1940 // block this page and open it in browser
1941 LogDebug("Request was blocked by WARP: " << url.c_str());
1942 if (!m_blockedUri.empty()) {
1943 LogDebug("open browser : " << m_blockedUri);
1944 bundle* bundleData = bundle_create();
1945 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
1946 appsvc_set_uri(bundleData, m_blockedUri.c_str());
1947 CONTROLLER_POST_EVENT(
1948 ApplicationLauncher,
1949 ApplicationLauncherEvents::LaunchApplicationByAppService(
1953 m_blockedUri = std::string();
1956 if (ewk_view_back_possible(m_currentEwkView)) {
1957 // go back to previous page
1958 ewk_view_back(m_currentEwkView);
1960 // stop current page
1961 ewk_view_stop(m_currentEwkView);
1962 ecore_idler_add(windowCloseIdlerCallback, this);
1965 // This is used in case of returning previous page
1967 return URICHANGE_PLUGIN_NO_CHANGE;
1972 // Check if this url with 'http' or 'https' is included in whitelist,
1973 // which has lists of accessible external documents and
1974 // used for ONLY Tizen app
1975 std::string matchedScheme;
1976 std::string matchedUri;
1977 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
1980 ViewModule::Scheme scheme(matchedScheme);
1981 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
1982 scheme.GetType() == ViewModule::Scheme::HTTPS)
1984 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1985 if (!checkWhitelist(url.c_str())) {
1986 LogInfo("This uri is not included in white document list");
1987 return URICHANGE_PLUGIN_STOP_ONLY;
1989 LogInfo("This url is included in WhiteList");
1991 // For WAC app, WRT should block access of device api
1992 // for external documents
1993 return URICHANGE_PLUGIN_STOP_ONLY;
1997 // register javascript object for plugins to be used
1998 LogInfo("Register Plugin Objects");
1999 return URICHANGE_PLUGIN_RESTART;
2002 void ViewLogic::windowClose()
2004 LogDebug("windowClose");
2005 Assert(m_closedEwkView && "no closed webview");
2007 if (1 >= m_ewkViewList.size()) {
2008 if (!m_cbs->webkitExit.empty()) {
2009 m_cbs->webkitExit();
2012 // call user callbacks
2013 if (!m_cbs->bufferUnset.empty()) {
2014 m_cbs->bufferUnset(m_currentEwkView);
2016 if (!m_cbs->windowClose.empty()) {
2017 m_cbs->windowClose(m_closedEwkView);
2019 removeEwkView(m_closedEwkView);
2021 // get latest ewkView
2022 m_currentEwkView = m_ewkViewList.back();
2023 const char* uri = ewk_view_url_get(m_currentEwkView);
2024 if (NULL == uri || 0 == strlen(uri)) {
2025 m_currentUri.clear();
2031 /* In case we support many pages in parallel
2032 then view is not suspended*/
2033 //resumeEwkView(m_currentEwkView);
2036 if (!m_cbs->bufferSet.empty()) {
2037 m_cbs->bufferSet(m_currentEwkView);