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>
32 #include <appcore-common.h>
35 #include <widget_model.h>
36 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
37 #include <dpl/utils/wrt_global_settings.h>
39 #include <common/application_data.h>
40 #include <common/application_launcher.h>
41 #include <common/scheme.h>
43 #include <common/view_logic_apps_support.h>
44 #include <common/view_logic_custom_header_support.h>
45 #include <common/view_logic_password_support.h>
46 #include <common/view_logic_security_support.h>
47 #include <common/view_logic_security_origin_support.h>
48 #include <common/view_logic_storage_support.h>
49 #include <common/view_logic_uri_support.h>
50 #include <common/view_logic_user_agent_support.h>
51 #include <common/view_logic_vibration_support.h>
52 #include <common/view_logic_web_notification_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_web_storage_support.h>
57 #include "bundles/plugin_module_support.h"
58 #include <popup-runner/PopupInvoker.h>
61 #include <js_overlay_types.h>
62 #include <i_runnable_widget_object.h>
63 #include <profiling_util.h>
64 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
65 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
66 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
67 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
69 #include <appsvc/appsvc.h>
72 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
73 const char * const uriBlockedMessageName = "uri_block_msg";
74 const char * const uriChangedMessageName = "uri_changed_msg";
75 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
76 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
77 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
78 const char * const URICHANGE_BLOCKED_URL = "null";
79 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
80 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
82 const char * const IME_STATE_ON = "on";
83 const char * const IME_STATE_OFF = "off";
86 const char * const EWK_LOAD_STARTED = "load,started";
87 const char * const EWK_LOAD_FINISHED = "load,finished";
88 const char * const EWK_TITLE_CHANGED = "title,changed";
89 const char * const EWK_LOAD_PROGRESS = "load,progress";
90 const char * const EWK_LOAD_PROGRESS_FINISHED = "load,progress,finished";
91 const char * const EWK_PROCESS_CRASHED = "process,crashed";
93 const char * const EWK_CREATE_WINDOW = "create,window";
94 const char * const EWK_CLOSE_WINDOW = "close,window";
96 const char * const EWK_POLICY_NAVIGATION_DECIDE = "policy,navigation,decide";
97 const char * const EWK_POLICY_NEWWINDOW_DECIDE = "policy,newwindow,decide";
98 const char * const EWK_POLICY_RESPONSE_DECIDE = "policy,response,decide";
99 // WKPageContextMenuClient
100 const char * const EWK_CONTEXTMENU_CUSTOMIZE = "contextmenu,customize";
102 const char * const EWK_FORM_SUBMIT = "form,submit";
103 // EWK Geolocation Callback
104 const char * const EWK_REQUEST_GEOLOCATION_PERMISSION =
105 "request,geolocation,permission";
106 // EWK Notification Callback
107 const char * const EWK_NOTIFICATION_SHOW = "notification,show";
108 const char * const EWK_NOTIFICATION_CANCEL = "notification,cancel";
109 const char * const EWK_NOTIFICATION_PERMISSION_REQUEST =
110 "notification,permission,request";
111 // EWK Vibration Callback
112 const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
113 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
115 const char * const EWK_CONTEXT_EXCEEDED_QUOATA = "database,quota,exceeded";
116 const char * const EWK_FILESYSTEM_PERMISSION_REQUEST = "filesystem,permission,request";
117 const char * const EWK_FULLSCREEN_ENTER = "fullscreen,enterfullscreen";
118 const char * const EWK_FULLSCREEN_EXIT = "fullscreen,exitfullscreen";
121 const char * const EWK_INPUTMETHOD_CHANGED = "inputmethod,changed";
122 const char * const EWK_EDITORCLIENT_IME_OPENED = "editorclient,ime,opened";
123 const char * const EWK_EDITORCLIENT_IME_CLOSED = "editorclient,ime,closed";
126 const char * const EWK_PROTOCOLHANDLER_REGISTRATION = "protocolhandler,registration,requested";
127 const char * const EWK_PROTOCOLHANDLER_ISREGISTERED = "protocolhandler,isregistered";
128 const char * const EWK_PROTOCOLHANDLER_UNREGISTRATION = "protocolhandler,unregistration,requested";
129 const char * const EWK_CONTENTHANDLER_REGISTRATION = "contenthandler,registration,requested";
130 const char * const EWK_CONTENTHANDLER_ISREGISTERED = "contenthandler,isregistered";
131 const char * const EWK_CONTENTHANDLER_UNREGISTRATION = "contenthandler,unregistration,requested";
133 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
134 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
135 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
136 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
137 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
138 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
141 ViewLogic::ViewLogic():
146 m_cbs(new WRT::UserDelegates),
147 m_isBackgroundReload(false),
148 m_appsSupport(new ViewModule::AppsSupport()),
149 m_vibrationSupport(NULL),
150 m_attachedToCustomHandlerDao(false)
154 ViewLogic::~ViewLogic ()
156 detachFromCustomHandlersDao();
159 void ViewLogic::createWebView(Ewk_Context* context,
163 initializeEwkContext(context);
164 Assert(NULL != m_ewkContext);
167 createEwkView(evas_object_evas_get(m_window));
170 void ViewLogic::destroyWebView()
173 finalizeEwkContext();
177 void ViewLogic::initialize()
179 LogDebug("Initializing");
180 ApplicationLauncherSingleton::Instance().Touch();
181 appcore_set_event_callback(
182 APPCORE_EVENT_LOW_MEMORY,
183 &appcoreLowMemoryCallback,
187 void ViewLogic::terminate()
189 LogDebug("terminating view logic");
193 LogError("Widget model not created");
198 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
200 LogDebug("View prepare");
204 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
205 Assert(NULL != m_ewkContext);
208 ADD_PROFILING_POINT("initializeSupport", "start");
210 ADD_PROFILING_POINT("initializeSupport", "stop");
212 ewkClientInit(m_currentEwkView);
213 ADD_PROFILING_POINT("prepareEwkView", "start");
214 prepareEwkView(m_currentEwkView);
215 ADD_PROFILING_POINT("prepareEwkView", "stop");
216 initializePluginLoading();
219 void ViewLogic::showWidget()
221 LogDebug("showing widget");
222 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
223 if (m_currentUri.empty()) {
224 LogError("Localized current URI doesn't exist");
228 LogInfo("m_currentUri: " << m_currentUri);
231 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
233 if (!m_cbs->bufferSet.empty()) {
234 m_cbs->bufferSet(m_currentEwkView);
238 void ViewLogic::hideWidget()
240 LogDebug("hiding widget");
241 ViewModule::StorageSupport::deinitializeStorage(m_model);
242 m_appsSupport->deinitialize();
245 // m_vibrationSupport->deinitialize();
247 while (m_ewkViewList.size()) {
248 LogInfo("pop webview: " << m_ewkViewList.back());
249 removeEwkView(m_ewkViewList.back());
251 m_ewkViewList.clear();
254 void ViewLogic::suspendWidget()
256 LogInfo("Pausing widget");
259 LogDebug("Request bundle to suspend");
260 PluginModuleSupport::suspend(m_ewkContext);
262 if (!m_currentEwkView) {
263 LogWarning("Cannot suspend widget without view");
265 suspendWebkit(m_currentEwkView);
268 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
270 // call user callback
271 if (!m_cbs->suspend.empty()) {
272 m_cbs->suspend(true);
276 void ViewLogic::resumeWidget()
278 LogInfo("Resume widget");
281 LogDebug("Request bundle to resume");
282 PluginModuleSupport::resume(m_ewkContext);
284 if (m_currentEwkView) {
285 resumeWebkit(m_currentEwkView);
288 /* window system team recomend removing this win_raise code. */
291 elm_win_raise(m_window);
294 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
296 // call user callback
297 if (!m_cbs->resume.empty()) {
302 void ViewLogic::resetWidget()
304 LogInfo("Resetting Widget");
306 // check if already created webview exists
307 if (!m_ewkViewList.size()) {
308 // create new webview
309 createEwkView(evas_object_evas_get(m_window));
311 ewkClientInit(m_currentEwkView);
312 prepareEwkView(m_currentEwkView);
314 // check if current url is service url for this tizen service
315 std::string requestedUri =
316 ViewModule::UriSupport::getUri(m_model, m_startUrl);
317 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
318 DPL::FromUTF8String(requestedUri.c_str()),
321 const char* currentUri = ewk_view_url_get(m_currentEwkView);
322 if (!currentUri && 0 == strlen(currentUri)) {
323 LogError("Fail to get uri from ewk_view_url_get");
328 PluginModuleSupport::resume(m_ewkContext);
329 resumeWebkit(m_currentEwkView);
330 if (DPL::ToUTF8String(*servicedUri) == currentUri) {
331 LogInfo("current page is raised");
332 // set only encoded bundle
333 double scale = elm_config_scale_get();
334 PluginModuleSupport::setCustomProperties(
337 ApplicationDataSingleton::Instance().getEncodedBundle());
338 PluginModuleSupport::dispatchJavaScriptEvent(
340 WrtPlugins::W3C::ServiceCustomEvent,
343 LogInfo("service page is loaded");
344 m_currentUri = DPL::ToUTF8String(*servicedUri);
345 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
347 elm_win_raise(m_window);
348 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
351 // call user callback
352 if (!m_cbs->reset.empty()) {
355 if (!m_cbs->bufferSet.empty()) {
356 m_cbs->bufferSet(m_currentEwkView);
360 void ViewLogic::backward()
362 if (ewk_view_back_possible(m_currentEwkView)) {
363 ewk_view_back(m_currentEwkView);
365 if (1 >= m_ewkViewList.size()) {
366 // If there is no previous page, widget move to backgroud.
367 LogInfo("Widget move to backgroud");
368 elm_win_lower(m_window);
370 // Back to previous webview
371 LogInfo("Widget move to previous webview");
372 ecore_idler_add(windowCloseIdlerCallback, this);
377 void ViewLogic::reload()
379 ewk_view_reload(m_currentEwkView);
382 void ViewLogic::forward()
384 if (ewk_view_forward_possible(m_currentEwkView)) {
385 ewk_view_forward(m_currentEwkView);
389 void ViewLogic::reloadStartPage()
391 LogInfo("Reload Start Page");
392 // prevent fail to load plugin bundle side
393 m_isBackgroundReload = true;
394 PluginModuleSupport::resume(m_ewkContext);
396 if (m_ewkViewList.size() != 0) {
397 while (m_ewkViewList.size() > 0) {
398 if (!m_cbs->bufferUnset.empty()) {
399 m_cbs->bufferUnset(m_currentEwkView);
401 removeEwkView(m_currentEwkView);
405 // create new webview
406 createEwkView(evas_object_evas_get(m_window));
407 ewkClientInit(m_currentEwkView);
410 prepareEwkView(m_currentEwkView);
411 initializePluginLoading();
414 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
417 if (!m_cbs->bufferSet.empty()) {
418 m_cbs->bufferSet(m_currentEwkView);
420 LogInfo("Reloading Start Page is done!");
423 Evas_Object* ViewLogic::getCurrentWebview()
425 LogInfo("get current webview");
426 return m_currentEwkView;
429 void ViewLogic::fireJavascriptEvent(int event, void* data)
431 PluginModuleSupport::dispatchJavaScriptEvent(
433 static_cast<WrtPlugins::W3C::CustomEventType>(event),
437 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
442 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
444 LogInfo("initializeEwkContext called");
445 Assert(newEwkContext && "Ewk_Context provided can not be null");
446 // bundle callback setting
447 ewk_context_message_from_injected_bundle_callback_set(
449 contextMessageFromInjectedBundleCallback,
450 static_cast<void*>(this));
452 // proxy server setting
453 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
454 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
455 || (strstr(proxyAddress, "0.0.0.0")))
457 LogInfo("proxy address is empty");
458 ewk_context_proxy_uri_set(newEwkContext, NULL);
460 LogInfo("proxy address [" << proxyAddress << "]");
461 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
470 const char *theme = elm_theme_get(NULL);
473 LogInfo("theme is " << m_theme);
476 // Ewk download callback (WKContextDownloadClient)
477 ewk_context_did_start_download_callback_set(
479 didStartDownloadCallback,
482 // set to member value
483 m_ewkContext = newEwkContext;
486 void ViewLogic::finalizeEwkContext()
488 LogInfo("finalizeEwkContext called");
489 ewk_context_message_from_injected_bundle_callback_set(
493 // ewk_context_delete(m_ewkContext);
497 void ViewLogic::initializeSupport()
499 // set local stroage database path
500 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
501 ewk_context_web_storage_path_set(m_ewkContext,
502 dao.getPrivateLocalStoragePath().c_str());
503 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
504 ViewModule::StorageSupport::initializeStorage(m_model);
505 m_appsSupport->initialize(m_model);
506 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
509 // m_vibrationSupport->initialize();
512 void ViewLogic::initializePluginLoading()
514 // inform wrt information for plugin loading to web process
515 PluginModuleSupport::start(
518 elm_config_scale_get(),
519 ApplicationDataSingleton::Instance().getEncodedBundle(),
521 m_model->SettingList.Get().isEncrypted());
524 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
525 Assert(NULL != wkView && "ewk_view not created at this point");
526 // WKPageLoaderClient
527 evas_object_smart_callback_add(
532 evas_object_smart_callback_add(
535 loadFinishedCallback,
537 evas_object_smart_callback_add(
540 titleChangedCallback,
542 evas_object_smart_callback_add(
545 loadProgressCallback,
547 evas_object_smart_callback_add(
549 EWK_LOAD_PROGRESS_FINISHED,
550 loadProgressFinishedCallback,
552 evas_object_smart_callback_add(
555 processCrashedCallback,
559 evas_object_smart_callback_add(
562 createWindowCallback,
564 evas_object_smart_callback_add(
570 // WKPagePolicyClient
571 evas_object_smart_callback_add(
573 EWK_POLICY_NAVIGATION_DECIDE,
574 policyNavigationDecideCallback,
576 evas_object_smart_callback_add(
578 EWK_POLICY_NEWWINDOW_DECIDE,
579 policyNewWindowDecideCallback,
581 evas_object_smart_callback_add(
583 EWK_POLICY_RESPONSE_DECIDE,
584 pageResponseDecideCallback,
587 // WKPageContextMenuClient
588 evas_object_smart_callback_add(
590 EWK_CONTEXTMENU_CUSTOMIZE,
591 contextmenuCustomizeCallback,
595 evas_object_smart_callback_add(
601 // EWK Geolocation Callback
602 evas_object_smart_callback_add(
604 EWK_REQUEST_GEOLOCATION_PERMISSION,
605 geolocationPermissionRequestCallback,
608 // EWK Notification Callback
609 evas_object_smart_callback_add(
611 EWK_NOTIFICATION_SHOW,
612 notificationShowCallback,
614 evas_object_smart_callback_add(
616 EWK_NOTIFICATION_CANCEL,
617 notificationCancelCallback,
619 evas_object_smart_callback_add(
621 EWK_NOTIFICATION_PERMISSION_REQUEST,
622 notificationPermissionRequestCallback,
625 // EWK Vibration Callback
626 evas_object_smart_callback_add(
628 EWK_VIBRATION_VIBRATE,
629 vibrationVibrateCallback,
631 evas_object_smart_callback_add(
633 EWK_VIBRATION_CANCEL,
634 vibrationCancelCallback,
636 evas_object_smart_callback_add(
638 EWK_CONTEXT_EXCEEDED_QUOATA,
639 databaseUsagePermissionRequestCallback,
641 evas_object_smart_callback_add(
643 EWK_FILESYSTEM_PERMISSION_REQUEST,
644 fileSystemPermissionRequestCallback,
647 // EWK Orientation Callback
648 //ewk_view_orientation_lock_callback_set(
650 // orientationLockCallback,
653 // Fullscreen API callbacks
654 evas_object_smart_callback_add(
656 EWK_FULLSCREEN_ENTER,
657 enterFullscreenCallback,
659 evas_object_smart_callback_add(
662 exitFullscreenCallback,
666 // when ime start to be showed on the webview,
667 // this callback will be called
668 evas_object_smart_callback_add(
670 EWK_INPUTMETHOD_CHANGED,
674 // this callback will be called
675 // when ime finishes to be showed on the webview
676 // "event_info" arg of this callback is always NULL point
677 // if web content should know size of ime,
678 // use "inputmethod,changed" instead of this.
680 evas_object_smart_callback_add(
682 EWK_EDITORCLIENT_IME_OPENED,
686 // when ime finished to be hidden,
687 // this callback will be called
688 evas_object_smart_callback_add(
690 EWK_EDITORCLIENT_IME_CLOSED,
694 // custom content/scheme handlers
695 evas_object_smart_callback_add(
697 EWK_PROTOCOLHANDLER_REGISTRATION,
698 protocolHandlerRegistrationCallback,
700 evas_object_smart_callback_add(
702 EWK_PROTOCOLHANDLER_ISREGISTERED,
703 protocolHandlerIsRegisteredCallback,
705 evas_object_smart_callback_add(
707 EWK_PROTOCOLHANDLER_UNREGISTRATION,
708 protocolHandlerUnregistrationCallback,
711 evas_object_smart_callback_add(
713 EWK_CONTENTHANDLER_REGISTRATION,
714 contentHandlerRegistrationCallback,
716 evas_object_smart_callback_add(
718 EWK_CONTENTHANDLER_ISREGISTERED,
719 contentHandlerIsRegisteredCallback,
721 evas_object_smart_callback_add(
723 EWK_CONTENTHANDLER_UNREGISTRATION,
724 contentHandlerUnregistrationCallback,
728 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
729 LogDebug("ewkClientDeinit");
730 Assert(NULL != wkView && "ewk_view not created at this point");
732 // WKPageLoaderClient
733 evas_object_smart_callback_del(
736 loadStartedCallback);
737 evas_object_smart_callback_del(
740 loadFinishedCallback);
741 evas_object_smart_callback_del(
744 titleChangedCallback);
745 evas_object_smart_callback_del(
748 loadProgressCallback);
749 evas_object_smart_callback_del(
751 EWK_LOAD_PROGRESS_FINISHED,
752 loadProgressFinishedCallback);
753 evas_object_smart_callback_del(
756 loadProgressCallback);
759 evas_object_smart_callback_del(
762 createWindowCallback);
763 evas_object_smart_callback_del(
766 closeWindowCallback);
768 // WKPagePolicyClient
769 evas_object_smart_callback_del(
771 EWK_POLICY_NAVIGATION_DECIDE,
772 policyNavigationDecideCallback);
773 evas_object_smart_callback_del(
775 EWK_POLICY_NEWWINDOW_DECIDE,
776 policyNewWindowDecideCallback);
777 evas_object_smart_callback_del(
779 EWK_POLICY_RESPONSE_DECIDE,
780 pageResponseDecideCallback);
782 // WKPageContextMenuClient
783 evas_object_smart_callback_del(
785 EWK_CONTEXTMENU_CUSTOMIZE,
786 contextmenuCustomizeCallback);
789 evas_object_smart_callback_del(
794 // EWK Geolocation Callback
795 evas_object_smart_callback_del(
797 EWK_REQUEST_GEOLOCATION_PERMISSION,
798 geolocationPermissionRequestCallback);
800 // EWK Notification Callback
801 evas_object_smart_callback_del(
803 EWK_NOTIFICATION_SHOW,
804 notificationShowCallback);
805 evas_object_smart_callback_del(
807 EWK_NOTIFICATION_CANCEL,
808 notificationCancelCallback);
809 evas_object_smart_callback_del(
811 EWK_NOTIFICATION_PERMISSION_REQUEST,
812 notificationPermissionRequestCallback);
814 // EWK Vibration Callback
815 evas_object_smart_callback_del(
817 EWK_VIBRATION_VIBRATE,
818 vibrationVibrateCallback);
819 evas_object_smart_callback_del(
821 EWK_VIBRATION_CANCEL,
822 vibrationCancelCallback);
824 evas_object_smart_callback_del(
826 EWK_CONTEXT_EXCEEDED_QUOATA,
827 databaseUsagePermissionRequestCallback);
828 evas_object_smart_callback_del(
830 EWK_FILESYSTEM_PERMISSION_REQUEST,
831 fileSystemPermissionRequestCallback);
833 // EWK Orientation Callback
834 //ewk_view_orientation_lock_callback_set(
839 // ime change/show/hide callback
840 evas_object_smart_callback_del(
842 EWK_INPUTMETHOD_CHANGED,
844 evas_object_smart_callback_del(
846 EWK_EDITORCLIENT_IME_OPENED,
848 evas_object_smart_callback_del(
850 EWK_EDITORCLIENT_IME_CLOSED,
853 // custom content/scheme handlers
854 evas_object_smart_callback_del(
856 EWK_PROTOCOLHANDLER_REGISTRATION,
857 protocolHandlerRegistrationCallback);
858 evas_object_smart_callback_del(
860 EWK_PROTOCOLHANDLER_ISREGISTERED,
861 protocolHandlerIsRegisteredCallback);
862 evas_object_smart_callback_del(
864 EWK_PROTOCOLHANDLER_UNREGISTRATION,
865 protocolHandlerUnregistrationCallback);
867 evas_object_smart_callback_del(
869 EWK_CONTENTHANDLER_REGISTRATION,
870 contentHandlerRegistrationCallback);
871 evas_object_smart_callback_del(
873 EWK_CONTENTHANDLER_ISREGISTERED,
874 contentHandlerIsRegisteredCallback);
875 evas_object_smart_callback_del(
877 EWK_CONTENTHANDLER_UNREGISTRATION,
878 contentHandlerUnregistrationCallback);
881 void ViewLogic::createEwkView(Evas* canvas)
883 LogDebug("createEwkVeiw");
885 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
886 Evas_Object* newEwkView = ewk_view_add_with_context(
889 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
892 LogError("WKView creation failed");
897 // even arguments pass the ewkContext, this API should be called
898 // after webkit Evas_Object is created
899 Ewk_Cookie_Manager *ewkCookieManager;
901 ewk_context_cookie_manager_get(m_ewkContext);
902 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
903 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
905 LogInfo("push webview: " << newEwkView);
906 m_ewkViewList.push_back(newEwkView);
907 m_currentEwkView = newEwkView;
910 void ViewLogic::setStartPage()
912 /* Start URI (as other uris) is now localized
913 * on WebProcess side */
914 m_currentUri = m_startUrl;
917 void ViewLogic::prepareEwkView(Evas_Object *wkView)
919 LogDebug("prepareEwkView called");
921 Ewk_Settings* settings = ewk_view_settings_get(wkView);
924 auto userAgentString =
925 ViewModule::UserAgentSupport::getUserAgentFromVconf();
926 if (!userAgentString.empty()) {
927 LogDebug("Setting custom user agent as: " << userAgentString);
928 ewk_view_user_agent_set(wkView, userAgentString.c_str());
931 // set custom header : language
932 using namespace ViewModule::CustomHeaderSupport;
933 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
934 if (!customHeaderString.empty()) {
935 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
936 LogDebug("custom value=[" << customHeaderString << "]");
937 ewk_view_custom_header_add(wkView,
938 ACCEPT_LANGUAGE.c_str(),
939 customHeaderString.c_str());
942 // webkit NPAPI plugins is always on in wrt
943 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
945 // The followings are not implemeted yet by webkit2
946 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
947 // ewk_view_mode_set();
948 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
949 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
950 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
951 // elm_webview_show_magnifier_set(EINA_FALSE);
952 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
953 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
954 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
956 // disable zoom option when user click the input field
957 // this option is useful with the normal website
958 // for the make user friendly, disable auto zoom in the webapp
959 // The followings are not implemeted yet by webkit2
960 // elm_webview_input_field_zoom_set(EINA_FALSE);
962 // set cookie database path
963 // The followings are not implemeted yet by webkit2
964 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
966 // set visibility to WebCore. This value will be used for html5.
967 // also, this value will be changed in the suspend, resume
968 // or create window, close window.
969 ewk_view_page_visibility_state_set(wkView,
970 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
974 void ViewLogic::removeEwkView(Evas_Object *wkView)
976 LogInfo("removeEwkView called");
978 Assert(0 != m_ewkViewList.size());
980 // unregister webview callbacks
981 ewkClientDeinit(wkView);
983 // suspend NPAPI plugin - Not implemented by Webkit2
984 // ewk_view_pause_or_resume_plugins();
985 evas_object_del(wkView);
986 m_ewkViewList.remove(wkView);
989 void ViewLogic::resumeEwkView(Evas_Object *wkView)
991 LogInfo("resumeEwkView called");
994 // register webview callback
995 ewkClientInit(wkView);
998 resumeWebkit(wkView);
1003 void ViewLogic::suspendEwkView(Evas_Object *wkView)
1005 LogInfo("suspendEwkView called");
1009 suspendWebkit(wkView);
1011 // unregister webview callbacks
1012 ewkClientDeinit(wkView);
1017 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1019 LogDebug("resumeWebkit");
1022 // resume NPAPI plugin
1023 // The followings are not implemeted yet by webkit2
1024 // ewk_view_pause_or_resume_plugins(false);
1025 // ewk_view_pause_or_resume_video_audio(false);
1026 // ewk_view_javascript_resume();
1027 // ewk_view_enable_render();
1028 // ewk_view_reduce_plugins_frame_rate(false);
1029 ewk_view_resume(wkView);
1030 ewk_view_visibility_set(wkView, EINA_TRUE);
1031 ewk_view_page_visibility_state_set(wkView,
1032 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
1037 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1039 LogDebug("suspendWebkit");
1042 // suspend the followings
1043 // The followings are not implemeted yet by webkit2
1044 // ewk_view_pause_or_resume_plugins(true);
1045 // ewk_view_pause_or_resume_video_audio(true);
1047 // send visibility event to webpage
1048 ewk_view_page_visibility_state_set(wkView,
1049 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1051 ewk_view_suspend(wkView);
1052 ewk_view_visibility_set(wkView, EINA_FALSE);
1056 void ViewLogic::contextMessageFromInjectedBundleCallback(
1062 LogDebug("contextMessageFromInjectedBundleCallback called");
1064 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1065 // didRecieveMessageFromInjectedBundleCallback - returnData is null
1066 // didReceiveSynchronousMessageCallback - returnData isn't null
1067 // WKContextInjectedBundleClient bundleClient = {
1068 // kWKContextInjectedBundleClientCurrentVersion,
1069 // static_cast<void*>(this),
1070 // &didRecieveMessageFromInjectedBundleCallback,
1071 // &didReceiveSynchronousMessageCallback
1073 if (NULL == returnData) {
1074 This->didRecieveMessageFromInjectedBundle(name, body);
1076 This->didReceiveSynchronousMessage(name, body, returnData);
1080 void ViewLogic::didStartDownloadCallback(
1081 const char* downloadUrl,
1084 LogDebug("didStartDownloadCallback called");
1086 ViewLogic* This = static_cast<ViewLogic*>(data);
1087 Assert(downloadUrl);
1088 LogDebug("download url = " << downloadUrl);
1089 This->m_appsSupport->downloadRequest(
1095 void ViewLogic::loadStartedCallback(
1098 void* /*eventInfo*/)
1100 LogDebug("loadStartedCallback called");
1102 ViewLogic* This = static_cast<ViewLogic*>(data);
1103 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1105 // call loadFinish callback to wrt-client
1106 if (!This->m_cbs->loadStart.empty()) {
1107 This->m_cbs->loadStart(obj);
1112 void ViewLogic::loadFinishedCallback(
1115 void* /*eventInfo*/)
1117 LogDebug("loadFinishedCallback called");
1119 ViewLogic* This = static_cast<ViewLogic*>(data);
1122 const char* url = ewk_view_url_get(This->m_currentEwkView);
1123 if (NULL == url || strlen(url) == 0) {
1124 LogError("url is empty");
1126 DPL::OptionalString jsOptionalString =
1127 ViewModule::PasswordSupport::jsForAutoFillData(url);
1128 if (jsOptionalString.IsNull()) {
1129 LogError("Fail to get JS String");
1131 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1133 if(EINA_FALSE == ewk_view_script_execute(
1134 This->m_currentEwkView,
1136 didRunJavaScriptCallback,
1139 LogError("JS for auto fill data failed.");
1144 // call loadFinish callback to wrt-client
1145 if (!This->m_cbs->loadFinish.empty()) {
1146 This->m_cbs->loadFinish(obj);
1149 // set only encoded bundle
1150 double scale = elm_config_scale_get();
1151 PluginModuleSupport::setCustomProperties(
1154 ApplicationDataSingleton::Instance().getEncodedBundle());
1155 // check if 'appsevice' event is registed at the current frames.
1156 // If so, dispatch the event to frames.
1157 PluginModuleSupport::dispatchJavaScriptEvent(
1159 WrtPlugins::W3C::ServiceCustomEvent,
1162 // In this case, widget is reloaded in the background.
1163 // After finished load, bundle should disconnent callback.
1164 if (This->m_isBackgroundReload) {
1165 PluginModuleSupport::suspend(This->m_ewkContext);
1166 ewk_view_suspend(This->m_currentEwkView);
1167 This->m_isBackgroundReload = false;
1171 void ViewLogic::titleChangedCallback(
1173 Evas_Object* /*obj*/,
1176 LogDebug("titleChangedCallback called");
1178 ViewLogic* This = static_cast<ViewLogic*>(data);
1180 const char* title = static_cast<char*>(eventInfo);
1182 if (0 == strlen(title)) {
1183 LogDebug("title data is empty");
1186 LogDebug("Title = [" << title << "]");
1187 This->m_schemeSupport->HandleTizenScheme(title,
1189 This->m_currentEwkView);
1192 void ViewLogic::loadProgressCallback(
1194 Evas_Object* /*obj*/,
1197 double* progress = static_cast<double*>(eventInfo);
1198 LogDebug("didChangeProgressCallback progress = " << *progress);
1201 void ViewLogic::loadProgressFinishedCallback(
1203 Evas_Object* /*obj*/,
1204 void* /*eventInfo*/)
1206 LogDebug("didFinishProgressCallback");
1208 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1209 if (!view->m_cbs->progressFinish.empty()) {
1210 view->m_cbs->progressFinish();
1214 void ViewLogic::processCrashedCallback(
1216 Evas_Object* /*obj*/,
1219 LogInfo("processCrashedCallback");
1221 ViewLogic const * const view =
1222 static_cast<ViewLogic const * const>(data);
1223 if (!view->m_cbs->webCrash.empty()) {
1224 view->m_cbs->webCrash();
1226 // This flag will be prevented exit() call in the Webkit side
1227 if (NULL != eventInfo) {
1228 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1232 void ViewLogic::createWindowCallback(
1237 LogDebug("createWindowCallback");
1239 ViewLogic* This = static_cast<ViewLogic*>(data);
1241 // First, current webview should be handled by user callback
1242 if (!This->m_cbs->bufferUnset.empty()) {
1243 This->m_cbs->bufferUnset(obj);
1246 // this can be set by executable for specific purpose
1247 Evas* canvas = NULL;
1248 if (!This->m_cbs->windowCreateBefore.empty()) {
1249 // 'obj' is parent webview object
1250 This->m_cbs->windowCreateBefore(&canvas, obj);
1253 canvas = evas_object_evas_get(This->m_window);
1256 // create new ewkview
1257 This->createEwkView(canvas);
1258 Evas_Object* newEwkView = This->m_currentEwkView;
1260 // initialize new ewkview
1261 This->setStartPage();
1262 This->ewkClientInit(newEwkView);
1263 This->prepareEwkView(newEwkView);
1265 // Specific jobs of child, parent webview are handled by each executable
1266 if (!This->m_cbs->windowCreateAfter.empty()) {
1267 // 'obj' is parent webview, 'newEwkView' is child webview
1268 This->m_cbs->windowCreateAfter(obj, newEwkView);
1271 // Lastly, new webview should be handled by user callback
1272 if (!This->m_cbs->bufferSet.empty()) {
1273 This->m_cbs->bufferSet(newEwkView);
1275 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1278 void ViewLogic::closeWindowCallback(
1281 void* /*eventInfo*/)
1283 LogDebug("closeWindowCallback");
1284 ViewLogic* This = static_cast<ViewLogic*>(data);
1285 This->m_closedEwkView = obj;
1286 ecore_idler_add(windowCloseIdlerCallback, This);
1289 void ViewLogic::policyNavigationDecideCallback(
1291 Evas_Object* /*obj*/,
1294 LogDebug("policyNavigationDecideCallback called");
1296 ViewLogic* This = static_cast<ViewLogic*>(data);
1298 Ewk_Policy_Decision* policyDecision =
1299 static_cast<Ewk_Policy_Decision*>(eventInfo);
1301 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1305 This->m_currentEwkView))
1308 ewk_policy_decision_use(policyDecision);
1310 // check whether this is new empty window
1311 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1312 if(!activeUrl || 0 == strlen(activeUrl)) {
1314 * The view is empty and scheme has been handled externally. When
1315 * user gets back from the external application he'd see blank page
1316 * and won't be able to navigate back. This happens when window.open
1317 * is used to handle schemes like sms/mms/mailto (for example in
1318 * WAC web standards tests: WS-15XX).
1320 * To solve the problem, the empty view is removed from the stack
1321 * and the previous one is shown. This is not an elegant solution
1322 * but we don't have a better one.
1324 LogInfo("Scheme has been handled externally. Removing empty view.");
1325 if (ewk_view_back_possible(This->m_currentEwkView)) {
1326 // go back to previous WKPage
1327 ewk_view_back(This->m_currentEwkView);
1329 // stop current WKPage
1330 ewk_view_stop(This->m_currentEwkView);
1331 ecore_idler_add(windowCloseIdlerCallback, This);
1336 ewk_policy_decision_ignore(policyDecision);
1340 void ViewLogic::policyNewWindowDecideCallback(
1342 Evas_Object* /*obj*/,
1345 LogDebug("policyNewWindowDecideCallback called");
1347 ViewLogic* This = static_cast<ViewLogic*>(data);
1349 Ewk_Policy_Decision* policyDecision =
1350 static_cast<Ewk_Policy_Decision*>(eventInfo);
1352 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1356 This->m_currentEwkView))
1358 ewk_policy_decision_use(policyDecision);
1361 ewk_policy_decision_ignore(policyDecision);
1365 void ViewLogic::pageResponseDecideCallback(
1367 Evas_Object* /*obj*/,
1370 LogDebug("pageResponseDecideCallback called");
1372 ViewLogic* This = static_cast<ViewLogic*>(data);
1374 Ewk_Policy_Decision* policyDecision =
1375 static_cast<Ewk_Policy_Decision*>(eventInfo);
1376 Ewk_Policy_Decision_Type policyDecisionType =
1377 ewk_policy_decision_type_get(policyDecision);
1379 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1381 ewk_policy_decision_use(policyDecision);
1382 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1383 LogDebug("download");
1384 ewk_policy_decision_suspend(policyDecision);
1386 // get uri information
1387 const char* url = ewk_policy_decision_url_get(policyDecision);
1388 if (NULL == url || strlen(url) == 0) {
1389 LogDebug("url data is empty");
1390 ewk_policy_decision_use(policyDecision);
1393 LogDebug("url = [" << url << "]");
1395 // get content information
1396 const char* content =
1397 ewk_policy_decision_response_mime_get(policyDecision);
1398 LogDebug("content type = [" << content << "]");
1400 // get cookie information
1401 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1402 LogDebug("cookie = [" << cookie << "]");
1404 LogDebug("Content not supported, will be opened in external app");
1405 This->m_appsSupport->downloadRequest(
1409 ewk_policy_decision_ignore(policyDecision);
1410 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1412 ewk_policy_decision_ignore(policyDecision);
1414 LogDebug("Type isn't handled");
1415 ewk_policy_decision_ignore(policyDecision);
1419 void ViewLogic::contextmenuCustomizeCallback(
1421 Evas_Object* /*obj*/,
1424 LogDebug("contextmenuCustomizeCallback called");
1427 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1428 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1429 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1430 (This->m_model->SettingList.Get().getContextMenu()
1431 == ContextMenu_Disable))
1433 LogDebug("ContextMenu Disable!!");
1434 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1435 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1437 ewk_context_menu_item_remove(menu, item);
1440 LogDebug("ContextMenu Enable!!");
1441 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1442 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1444 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1447 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1448 ewk_context_menu_item_remove(menu, item);
1451 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1452 ewk_context_menu_item_remove(menu, item);
1463 void ViewLogic::formSubmitCallback(
1465 Evas_Object* /*obj*/,
1468 LogDebug("formSubmitCallback called");
1470 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1472 const char* uri = ewk_form_data_url_get(formData);
1474 LogError("URL is empty");
1478 Eina_Hash* userData = ewk_form_data_values_get(formData);
1479 ViewModule::PasswordSupport::submitClicked(uri, userData);
1482 void ViewLogic::geolocationPermissionRequestCallback(
1484 Evas_Object* /*obj*/,
1488 ViewLogic* This = static_cast<ViewLogic*>(data);
1490 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1492 This->m_securityOriginSupport->getSecurityOriginDAO(),
1496 void ViewLogic::notificationShowCallback(
1498 Evas_Object* /*obj*/,
1501 LogDebug("notificationShowCallback called");
1503 ViewLogic* This = static_cast<ViewLogic*>(data);
1506 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1508 using namespace ViewModule::WebNotification;
1510 WebNotificationDataPtr notiData(
1511 new WebNotificationData(
1513 ewk_notification_id_get(noti)));
1515 DPL::OptionalString string =
1516 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1517 if (!string.IsNull()) {
1518 notiData->m_iconURL = DPL::ToUTF8String(*string);
1520 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1521 if (!string.IsNull()) {
1522 notiData->m_title = DPL::ToUTF8String(*string);
1524 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1525 if (!string.IsNull()) {
1526 notiData->m_body = DPL::ToUTF8String(*string);
1529 LogInfo("notification id : " << notiData->m_id);
1530 LogInfo("notification iconURL : " << notiData->m_iconURL);
1531 LogInfo("notification title : " << notiData->m_title);
1532 LogInfo("notification body : " << notiData->m_body);
1534 showWebNotification(notiData);
1535 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1538 void ViewLogic::notificationCancelCallback(
1540 Evas_Object* /*obj*/,
1541 void* /*eventInfo*/)
1543 LogDebug("notificationCancelCallback called");
1546 void ViewLogic::notificationPermissionRequestCallback(
1548 Evas_Object* /*obj*/,
1551 LogDebug("notificationPermissionRequestCallback called");
1553 ViewLogic* This = static_cast<ViewLogic*>(data);
1556 Ewk_Notification_Permission_Request* request =
1557 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1558 ewk_notification_permission_request_response(
1565 void ViewLogic::vibrationVibrateCallback(
1567 Evas_Object* /*obj*/,
1570 LogDebug("vibrationVibrateCallback called");
1572 ViewLogic* This = static_cast<ViewLogic*>(data);
1575 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1578 // This->m_vibrationSupport->startVibration(vibrationTime);
1583 void ViewLogic::vibrationCancelCallback(
1585 Evas_Object* /*obj*/,
1586 void* /*eventInfo*/)
1588 LogDebug("vibrationCancelCallback called");
1590 ViewLogic* This = static_cast<ViewLogic*>(data);
1593 // This->m_vibrationSupport->stopVibration();
1598 // EWK Orientation Callback
1599 Eina_Bool ViewLogic::orientationLockCallback(
1601 Eina_Bool /*needLock*/,
1605 LogDebug("orientationLockCallback called");
1607 ViewLogic* This = static_cast<ViewLogic*>(data);
1609 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1610 LogDebug("orientation is portrait-primary");
1611 elm_win_rotation_with_resize_set(This->m_window, 0);
1612 ewk_view_orientation_send(obj, 0);
1613 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1614 LogDebug("orientation is landscape-primary");
1615 elm_win_rotation_with_resize_set(This->m_window, 270);
1616 ewk_view_orientation_send(obj, 90);
1617 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1618 LogDebug("orientation is portrait-secondary");
1619 elm_win_rotation_with_resize_set(This->m_window, 180);
1620 ewk_view_orientation_send(obj, 180);
1621 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1622 LogDebug("orientation is landscape-secondary");
1623 elm_win_rotation_with_resize_set(This->m_window, 90);
1624 ewk_view_orientation_send(obj, -90);
1626 LogDebug("Wrong orientation is set");
1633 // Fullscreen API callbacks
1634 void ViewLogic::enterFullscreenCallback(
1636 Evas_Object* /*obj*/,
1637 void* /*eventInfo*/)
1639 LogInfo("enterFullscreenCallback called");
1641 ViewLogic* This = static_cast<ViewLogic*>(data);
1642 if (!This->m_cbs->toggleFullscreen.empty()) {
1643 This->m_cbs->toggleFullscreen(true);
1646 void ViewLogic::exitFullscreenCallback(
1648 Evas_Object* /*obj*/,
1649 void* /*eventInfo*/)
1651 LogInfo("exitFullscreenCallback called");
1653 ViewLogic* This = static_cast<ViewLogic*>(data);
1654 if (!This->m_cbs->toggleFullscreen.empty()) {
1655 This->m_cbs->toggleFullscreen(false);
1659 void ViewLogic::imeChangedCallback(
1661 Evas_Object* /*obj*/,
1667 ViewLogic* This = static_cast<ViewLogic*>(data);
1668 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1669 This->m_imeWidth = rect->w;
1670 This->m_imeHeight = rect->h;
1673 void ViewLogic::imeOpenedCallback(
1675 Evas_Object* /*obj*/,
1676 void* /*eventInfo*/)
1680 ViewLogic* This = static_cast<ViewLogic*>(data);
1682 using namespace WrtPlugins::W3C;
1683 SoftKeyboardChangeArgs args;
1684 args.state = IME_STATE_ON;
1685 args.width = This->m_imeWidth;
1686 args.height = This->m_imeHeight;
1687 This->fireJavascriptEvent(
1688 static_cast<int>(SoftKeyboardChangeCustomEvent),
1692 void ViewLogic::imeClosedCallback(
1694 Evas_Object* /*obj*/,
1695 void* /*eventInfo*/)
1699 ViewLogic* This = static_cast<ViewLogic*>(data);
1701 using namespace WrtPlugins::W3C;
1702 SoftKeyboardChangeArgs args;
1703 args.state = IME_STATE_OFF;
1705 This->fireJavascriptEvent(
1706 static_cast<int>(SoftKeyboardChangeCustomEvent),
1711 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1714 Ewk_Custom_Handlers_Data* handler =
1715 static_cast<Ewk_Custom_Handlers_Data*>(data);
1716 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1717 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1719 LogDebug("base url: " << base_url);
1720 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1722 const char* url = ewk_custom_handlers_data_url_get(handler);
1724 LogDebug("url: " << url);
1725 customHandler->url = DPL::FromASCIIString(string(url));
1727 const char* target = ewk_custom_handlers_data_target_get(handler);
1729 LogDebug("target: " << target);
1730 customHandler->target = DPL::FromASCIIString(string(target));
1732 const char* title = ewk_custom_handlers_data_title_get(handler);
1734 LogDebug("title: " << title);
1735 customHandler->title = DPL::FromASCIIString(string(title));
1737 return customHandler;
1740 void ViewLogic::attachToCustomHandlersDao()
1742 if (!m_attachedToCustomHandlerDao) {
1743 CustomHandlerDB::Interface::attachDatabaseRW();
1747 void ViewLogic::detachFromCustomHandlersDao()
1749 if (m_attachedToCustomHandlerDao) {
1750 CustomHandlerDB::Interface::detachDatabase();
1754 const int protocolWhiteListLenth = 15;
1755 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1773 const int contentBlackListLenth = 14;
1774 char const * const contentBlackList[contentBlackListLenth] = {
1775 "application/x-www-form-urlencoded",
1776 "application/xhtml+xml",
1782 "multipart/x-mixed-replace",
1783 "text/cache-manifest",
1792 * Saves user's response from popup to custom handler. Saves Yes/No and remember
1795 * @param customHandler
1797 void saveUserResponse(Wrt::Popup::PopupResponse response,
1798 CustomHandlerDB::CustomHandlerPtr customHandler)
1801 case Wrt::Popup::YES_DO_REMEMBER:
1802 LogDebug("User allowed, remember");
1803 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1804 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1806 case Wrt::Popup::YES_DONT_REMEMBER:
1807 LogDebug("User allowed, don't remember");
1808 customHandler->user_decision = CustomHandlerDB::Agreed;
1810 case Wrt::Popup::NO_DO_REMEMBER:
1811 LogDebug("User didn't allow, remember");
1812 customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1813 (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1815 case Wrt::Popup::NO_DONT_REMEMBER:
1816 LogDebug("User didn't allow, don't remember");
1817 customHandler->user_decision = CustomHandlerDB::Declined;
1822 //TODO registration, checking if registered and unregistration can be done in
1823 //common functions for both types of handlers. Only white and black lists
1824 //have to be separated
1825 //TODO attach database only one at the start (not in every callback?)
1826 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1832 CustomHandlerDB::CustomHandlerPtr customHandler =
1833 getCustomHandlerFromData(eventInfo);
1835 std::string scheme = DPL::ToUTF8String(customHandler->target);
1836 if (scheme.empty()) {
1837 LogError("No scheme provided");
1838 //TODO what about securityError?
1841 bool matched = false;
1842 //scheme on whiteList
1843 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1844 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1846 LogDebug("Match found, protocol can be handled");
1851 //starts with web+ and have at least 5 chars (lowercase ASCII)
1852 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1853 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1854 //throw SecurityException
1861 if (c < 'a' || c > 'z') {
1862 LogWarning("Wrong char inside scheme. "
1863 << "Only lowercase ASCII letters accepted");
1864 //throw SecurityException
1871 ViewLogic* This = static_cast<ViewLogic*>(data);
1872 LogDebug("Creating handlers dao");
1873 This->attachToCustomHandlersDao();
1874 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1875 CustomHandlerDB::CustomHandlerPtr handler =
1876 handlersDao.getProtocolHandler(customHandler->target,
1878 customHandler->base_url);
1879 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1880 LogDebug("Protocol already registered - nothing to do");
1882 LogDebug("Protocol handler not found");
1883 Wrt::Popup::PopupResponse response =
1884 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1885 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1886 PROTOCOL_HANDLER_ASK_TITLE,
1887 PROTOCOL_HANDLER_ASK_MSG,
1888 PROTOCOL_HANDLER_ASK_REMEMBER);
1889 saveUserResponse(response, customHandler);
1890 if (customHandler->user_decision == CustomHandlerDB::Declined)
1892 handlersDao.registerProtocolHandler(*(customHandler.get()));
1893 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1894 //TODO remove old default handler somehow from appsvc
1895 LogDebug("Registering appservice entry");
1896 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1898 DPL::ToUTF8String(customHandler->target).c_str(),
1899 DPL::ToUTF8String(This->m_model->TizenId).c_str());
1900 if (APPSVC_RET_OK != ret)
1902 LogWarning("Appsvc entry failed: " << ret);
1905 LogDebug("Protocal saved");
1908 This->detachFromCustomHandlersDao();
1911 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1916 CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1917 ViewLogic* This = static_cast<ViewLogic*>(data);
1918 LogDebug("Creating handlers dao");
1919 This->attachToCustomHandlersDao();
1920 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1921 CustomHandlerDB::CustomHandlerPtr handler =
1922 handlersDao.getProtocolHandler(customHandler->target,
1924 customHandler->base_url);
1926 if (handler->user_decision & CustomHandlerDB::Agreed)
1927 ewk_custom_handlers_data_result_set(
1928 static_cast<Ewk_Custom_Handlers_Data*>(data),
1929 EWK_CUSTOM_HANDLERS_REGISTERED);
1931 ewk_custom_handlers_data_result_set(
1932 static_cast<Ewk_Custom_Handlers_Data*>(data),
1933 EWK_CUSTOM_HANDLERS_DECLINED);
1935 ewk_custom_handlers_data_result_set(
1936 static_cast<Ewk_Custom_Handlers_Data*>(data),
1937 EWK_CUSTOM_HANDLERS_NEW);
1938 This->detachFromCustomHandlersDao();
1941 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1946 CustomHandlerDB::CustomHandlerPtr customHandler =
1947 getCustomHandlerFromData(eventInfo);
1948 ViewLogic* This = static_cast<ViewLogic*>(data);
1949 LogDebug("Creating handlers dao");
1950 This->attachToCustomHandlersDao();
1951 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1952 CustomHandlerDB::CustomHandlerPtr handlerCheck =
1953 handlersDao.getProtocolHandler(customHandler->target,
1955 customHandler->base_url);
1957 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1958 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1960 handlersDao.unregisterProtocolHandler(customHandler->target,
1962 customHandler->base_url);
1964 LogDebug("Nothing to unregister");
1966 This->detachFromCustomHandlersDao();
1969 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1975 CustomHandlerDB::CustomHandlerPtr customHandler =
1976 getCustomHandlerFromData(eventInfo);
1978 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1979 if (mimeType.empty()) {
1980 LogError("No mimeType provided.");
1983 for (int i = 0; i < contentBlackListLenth; ++i)
1985 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1987 LogWarning("mimeType blacklisted");
1988 //throw SecurityException
1993 ViewLogic* This = static_cast<ViewLogic*>(data);
1994 LogDebug("Creating handlers dao");
1995 This->attachToCustomHandlersDao();
1996 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1997 CustomHandlerDB::CustomHandlerPtr handler =
1998 handlersDao.getContentHandler(customHandler->target,
2000 customHandler->base_url);
2001 if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
2002 LogDebug("Protocol already registered - nothing to do");
2004 LogDebug("Protocol handler not found");
2005 Wrt::Popup::PopupResponse response =
2006 GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
2007 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
2008 CONTENT_HANDLER_ASK_TITLE,
2009 CONTENT_HANDLER_ASK_MSG,
2010 CONTENT_HANDLER_AKS_REMEMBER);
2011 saveUserResponse(response, customHandler);
2012 if (customHandler->user_decision == CustomHandlerDB::Declined)
2014 handlersDao.registerContentHandler(*(customHandler.get()));
2015 if (customHandler->user_decision & CustomHandlerDB::Agreed) {
2016 //TODO remove old default handler somehow from appsvc
2017 LogDebug("Registering appservice entry");
2018 int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
2019 DPL::ToUTF8String(customHandler->target).c_str(),
2021 DPL::ToUTF8String(This->m_model->TizenId).c_str());
2022 if (APPSVC_RET_OK != ret)
2024 LogWarning("Appsvc entry failed: " << ret);
2027 LogDebug("Content saved");
2029 This->detachFromCustomHandlersDao();
2032 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
2037 CustomHandlerDB::CustomHandlerPtr customHandler =
2038 getCustomHandlerFromData(eventInfo);
2039 ViewLogic* This = static_cast<ViewLogic*>(data);
2040 LogDebug("Creating handlers dao");
2042 This->attachToCustomHandlersDao();
2043 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2044 CustomHandlerDB::CustomHandlerPtr handler =
2045 handlersDao.getContentHandler(customHandler->target,
2047 customHandler->base_url);
2049 if (handler->user_decision & CustomHandlerDB::Agreed)
2050 ewk_custom_handlers_data_result_set(
2051 static_cast<Ewk_Custom_Handlers_Data*>(data),
2052 EWK_CUSTOM_HANDLERS_REGISTERED);
2054 ewk_custom_handlers_data_result_set(
2055 static_cast<Ewk_Custom_Handlers_Data*>(data),
2056 EWK_CUSTOM_HANDLERS_DECLINED);
2058 ewk_custom_handlers_data_result_set(
2059 static_cast<Ewk_Custom_Handlers_Data*>(data),
2060 EWK_CUSTOM_HANDLERS_NEW);
2061 This->detachFromCustomHandlersDao();
2064 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
2069 CustomHandlerDB::CustomHandlerPtr customHandler =
2070 getCustomHandlerFromData(eventInfo);
2071 ViewLogic* This = static_cast<ViewLogic*>(data);
2072 LogDebug("Creating handlers dao");
2073 This->attachToCustomHandlersDao();
2074 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2075 CustomHandlerDB::CustomHandlerPtr handlerCheck =
2076 handlersDao.getContentHandler(customHandler->target,
2078 customHandler->base_url);
2080 if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2081 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2083 handlersDao.unregisterContentHandler(customHandler->target,
2085 customHandler->base_url);
2087 LogDebug("Nothing to unregister");
2088 This->detachFromCustomHandlersDao();
2091 void ViewLogic::didRunJavaScriptCallback(
2092 Evas_Object* /*obj*/,
2096 LogInfo("didRunJavaScriptCallback called");
2097 LogInfo("result = " << result);
2100 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
2102 LogDebug("closeIdlerCallback");
2103 ViewLogic* This = static_cast<ViewLogic*>(data);
2104 This->windowClose();
2105 return ECORE_CALLBACK_CANCEL;
2108 int ViewLogic::appcoreLowMemoryCallback(void *data)
2110 LogInfo("appcoreLowMemoryCallback");
2112 ViewLogic* This = static_cast<ViewLogic*>(data);
2114 if (NULL == This->m_ewkContext) {
2115 LogInfo("ewk isn't initialize at this moment");
2117 // Crash may occur on specific situation
2118 // So use the followings after they become stable
2119 //ewk_context_cache_clear(This->m_ewkContext);
2120 //ewk_context_notify_low_memory(This->m_ewkContext);
2126 void ViewLogic::databaseUsagePermissionRequestCallback(
2128 Evas_Object* /*obj*/,
2131 LogDebug("databaseUsagePermissionRequestCallback called");
2133 ViewLogic* This = static_cast<ViewLogic*>(data);
2136 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
2138 This->m_securityOriginSupport->getSecurityOriginDAO(),
2143 void ViewLogic::fileSystemPermissionRequestCallback(
2145 Evas_Object* /*obj*/,
2148 LogDebug("fileSystemPermissionRequestCallback called");
2150 ViewLogic* This = static_cast<ViewLogic*>(data);
2152 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
2154 This->m_securityOriginSupport->getSecurityOriginDAO(),
2158 void ViewLogic::didRecieveMessageFromInjectedBundle(
2160 const char* /*body*/)
2162 LogDebug("did recive message " << name);
2165 void ViewLogic::didReceiveSynchronousMessage(
2170 LogDebug("didReceiveSynchronousMessage called");
2175 LogDebug("body is empty");
2179 if (!strcmp(name, uriBlockedMessageName)) {
2180 LogDebug("received : " << uriBlockedMessageName);
2181 // Currently WebProcess informs obly about blocked
2182 // URI - URI localization and security chekcs are
2183 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2184 // and bundle_uri_handling.cpp)
2185 rememberBlockedURI(DPL::FromUTF8String(body));
2187 } else if (!strcmp(name, uriChangedMessageName)) {
2188 LogDebug("received : " << uriChangedMessageName);
2189 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2190 *returnData = strdup(ret.c_str());
2194 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2196 m_blockedUri = DPL::ToUTF8String(inputURI);
2197 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2201 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2203 using namespace ViewModule::SecuritySupport;
2205 std::string url = DPL::ToUTF8String(changedURL);
2206 LogInfo("URL = [" << url << "]");
2209 // If url is same to URICHANGE_BLOCKED_URL,
2210 // this url has been already blocked by willsend.
2211 // So current page should be moved to previous page
2212 if (url == URICHANGE_BLOCKED_URL)
2214 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2216 // block this page and open it in browser
2217 LogDebug("Request was blocked by WARP: " << url.c_str());
2218 if (!m_blockedUri.empty()) {
2219 LogDebug("open browser : " << m_blockedUri);
2220 bundle* bundleData = bundle_create();
2221 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2222 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2223 CONTROLLER_POST_EVENT(
2224 ApplicationLauncher,
2225 ApplicationLauncherEvents::LaunchApplicationByAppService(
2229 m_blockedUri = std::string();
2232 if (ewk_view_back_possible(m_currentEwkView)) {
2233 // go back to previous page
2234 ewk_view_back(m_currentEwkView);
2236 // stop current page
2237 ewk_view_stop(m_currentEwkView);
2238 ecore_idler_add(windowCloseIdlerCallback, this);
2241 // This is used in case of returning previous page
2243 return URICHANGE_PLUGIN_NO_CHANGE;
2248 // Check if this url with 'http' or 'https' is included in whitelist,
2249 // which has lists of accessible external documents and
2250 // used for ONLY Tizen app
2251 std::string matchedScheme;
2252 std::string matchedUri;
2253 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2256 ViewModule::Scheme scheme(matchedScheme);
2257 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2258 scheme.GetType() == ViewModule::Scheme::HTTPS)
2260 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2261 if (!checkWhitelist(url.c_str())) {
2262 LogInfo("This uri is not included in white document list");
2263 return URICHANGE_PLUGIN_STOP_ONLY;
2265 LogInfo("This url is included in WhiteList");
2267 // For WAC app, WRT should block access of device api
2268 // for external documents
2269 return URICHANGE_PLUGIN_STOP_ONLY;
2273 // register javascript object for plugins to be used
2274 LogInfo("Register Plugin Objects");
2275 return URICHANGE_PLUGIN_RESTART;
2278 void ViewLogic::windowClose()
2280 LogDebug("windowClose");
2281 Assert(m_closedEwkView && "no closed webview");
2283 if (1 >= m_ewkViewList.size()) {
2284 if (!m_cbs->webkitExit.empty()) {
2285 m_cbs->webkitExit();
2288 // call user callbacks
2289 if (!m_cbs->bufferUnset.empty()) {
2290 m_cbs->bufferUnset(m_currentEwkView);
2292 if (!m_cbs->windowClose.empty()) {
2293 m_cbs->windowClose(m_closedEwkView);
2295 removeEwkView(m_closedEwkView);
2297 // get latest ewkView
2298 m_currentEwkView = m_ewkViewList.back();
2299 const char* uri = ewk_view_url_get(m_currentEwkView);
2300 if (NULL == uri || 0 == strlen(uri)) {
2301 m_currentUri.clear();
2307 /* In case we support many pages in parallel
2308 then view is not suspended*/
2309 //resumeEwkView(m_currentEwkView);
2312 if (!m_cbs->bufferSet.empty()) {
2313 m_cbs->bufferSet(m_currentEwkView);