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 <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
38 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.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 <common/view_logic_web_notification_support.h>
54 #include <view_logic_scheme_support.h>
55 #include <view_logic_filesystem_support.h>
56 #include <view_logic_geolocation_support_webkit2.h>
57 #include <view_logic_web_storage_support.h>
58 #include "bundles/plugin_module_support.h"
59 #include <popup-runner/PopupInvoker.h>
62 #include <js_overlay_types.h>
63 #include <i_runnable_widget_object.h>
64 #include <profiling_util.h>
67 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
68 const char * const uriBlockedMessageName = "uri_block_msg";
69 const char * const uriChangedMessageName = "uri_changed_msg";
70 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
71 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
72 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
73 const char * const URICHANGE_BLOCKED_URL = "null";
74 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
75 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
77 const char * const IME_STATE_ON = "on";
78 const char * const IME_STATE_OFF = "off";
81 const char * const EWK_LOAD_STARTED = "load,started";
82 const char * const EWK_LOAD_FINISHED = "load,finished";
83 const char * const EWK_TITLE_CHANGED = "title,changed";
84 const char * const EWK_LOAD_PROGRESS = "load,progress";
85 const char * const EWK_LOAD_PROGRESS_FINISHED = "load,progress,finished";
86 const char * const EWK_PROCESS_CRASHED = "process,crashed";
88 const char * const EWK_CREATE_WINDOW = "create,window";
89 const char * const EWK_CLOSE_WINDOW = "close,window";
91 const char * const EWK_POLICY_NAVIGATION_DECIDE = "policy,navigation,decide";
92 const char * const EWK_POLICY_NEWWINDOW_DECIDE = "policy,newwindow,decide";
93 const char * const EWK_POLICY_RESPONSE_DECIDE = "policy,response,decide";
94 // WKPageContextMenuClient
95 const char * const EWK_CONTEXTMENU_CUSTOMIZE = "contextmenu,customize";
97 const char * const EWK_FORM_SUBMIT = "form,submit";
98 // EWK Geolocation Callback
99 const char * const EWK_REQUEST_GEOLOCATION_PERMISSION =
100 "request,geolocation,permission";
101 // EWK Notification Callback
102 const char * const EWK_NOTIFICATION_SHOW = "notification,show";
103 const char * const EWK_NOTIFICATION_CANCEL = "notification,cancel";
104 const char * const EWK_NOTIFICATION_PERMISSION_REQUEST =
105 "notification,permission,request";
106 // EWK Vibration Callback
107 const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
108 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
110 const char * const EWK_CONTEXT_EXCEEDED_QUOATA = "database,quota,exceeded";
111 const char * const EWK_FILESYSTEM_PERMISSION_REQUEST = "filesystem,permission,request";
112 const char * const EWK_FULLSCREEN_ENTER = "fullscreen,enterfullscreen";
113 const char * const EWK_FULLSCREEN_EXIT = "fullscreen,exitfullscreen";
116 const char * const EWK_INPUTMETHOD_CHANGED = "inputmethod,changed";
117 const char * const EWK_EDITORCLIENT_IME_OPENED = "editorclient,ime,opened";
118 const char * const EWK_EDITORCLIENT_IME_CLOSED = "editorclient,ime,closed";
121 const char * const EWK_PROTOCOLHANDLER_REGISTRATION = "protocolhandler,registration,requested";
122 const char * const EWK_PROTOCOLHANDLER_ISREGISTERED = "protocolhandler,isregistered";
123 const char * const EWK_PROTOCOLHANDLER_UNREGISTRATION = "protocolhandler,unregistration,requested";
124 const char * const EWK_CONTENTHANDLER_REGISTRATION = "contenthandler,registration,requested";
125 const char * const EWK_CONTENTHANDLER_ISREGISTERED = "contenthandler,isregistered";
126 const char * const EWK_CONTENTHANDLER_UNREGISTRATION = "contenthandler,unregistration,requested";
128 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
129 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
130 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
131 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
134 ViewLogic::ViewLogic():
139 m_cbs(new WRT::UserDelegates),
140 m_appsSupport(new ViewModule::AppsSupport()),
141 m_vibrationSupport(NULL),
142 m_attachedToCustomHandlerDao(false)
146 ViewLogic::~ViewLogic ()
148 detachFromCustomHandlersDao();
151 void ViewLogic::createWebView(Ewk_Context* context,
155 initializeEwkContext(context);
156 Assert(NULL != m_ewkContext);
159 createEwkView(evas_object_evas_get(m_window));
162 void ViewLogic::destroyWebView()
165 finalizeEwkContext();
169 void ViewLogic::initialize()
171 LogDebug("Initializing");
172 ApplicationLauncherSingleton::Instance().Touch();
173 appcore_set_event_callback(
174 APPCORE_EVENT_LOW_MEMORY,
175 &appcoreLowMemoryCallback,
179 void ViewLogic::terminate()
181 LogDebug("terminating view logic");
185 LogError("Widget model not created");
190 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
192 LogDebug("View prepare");
196 m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
197 Assert(NULL != m_ewkContext);
200 ADD_PROFILING_POINT("initializeSupport", "start");
202 ADD_PROFILING_POINT("initializeSupport", "stop");
204 ewkClientInit(m_currentEwkView);
205 ADD_PROFILING_POINT("prepareEwkView", "start");
206 prepareEwkView(m_currentEwkView);
207 ADD_PROFILING_POINT("prepareEwkView", "stop");
208 initializePluginLoading();
211 void ViewLogic::showWidget()
213 LogDebug("showing widget");
214 Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
215 if (m_currentUri.empty()) {
216 LogError("Localized current URI doesn't exist");
220 LogInfo("m_currentUri: " << m_currentUri);
223 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
225 if (!m_cbs->bufferSet.empty()) {
226 m_cbs->bufferSet(m_currentEwkView);
230 void ViewLogic::hideWidget()
232 LogDebug("hiding widget");
233 ViewModule::StorageSupport::deinitializeStorage(m_model);
234 m_appsSupport->deinitialize();
237 // m_vibrationSupport->deinitialize();
239 while (m_ewkViewList.size()) {
240 LogInfo("pop webview: " << m_ewkViewList.back());
241 removeEwkView(m_ewkViewList.back());
243 m_ewkViewList.clear();
246 void ViewLogic::suspendWidget()
248 LogInfo("Pausing widget");
251 LogDebug("Request bundle to suspend");
252 PluginModuleSupport::suspend(m_ewkContext);
254 if (!m_currentEwkView) {
255 LogWarning("Cannot suspend widget without view");
257 suspendWebkit(m_currentEwkView);
260 evas_object_focus_set(m_currentEwkView, EINA_FALSE);
262 // call user callback
263 if (!m_cbs->suspend.empty()) {
264 m_cbs->suspend(true);
268 void ViewLogic::resumeWidget()
270 LogInfo("Resume widget");
273 LogDebug("Request bundle to resume");
274 PluginModuleSupport::resume(m_ewkContext);
276 if (m_currentEwkView) {
277 resumeWebkit(m_currentEwkView);
280 /* window system team recomend removing this win_raise code. */
283 elm_win_raise(m_window);
286 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
288 // call user callback
289 if (!m_cbs->resume.empty()) {
294 void ViewLogic::resetWidget()
296 LogInfo("Resetting Widget");
298 // check if already created webview exists
299 if (!m_ewkViewList.size()) {
300 // create new webview
301 createEwkView(evas_object_evas_get(m_window));
303 ewkClientInit(m_currentEwkView);
304 prepareEwkView(m_currentEwkView);
306 // check if current url is service url for this tizen service
307 std::string requestedUri =
308 ViewModule::UriSupport::getUri(m_model, m_startUrl);
309 DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
310 DPL::FromUTF8String(requestedUri.c_str()),
313 const char* currentUri = ewk_view_url_get(m_currentEwkView);
314 if (!currentUri && 0 == strlen(currentUri)) {
315 LogError("Fail to get uri from ewk_view_url_get");
320 PluginModuleSupport::resume(m_ewkContext);
321 resumeWebkit(m_currentEwkView);
322 if (DPL::ToUTF8String(*servicedUri) == currentUri) {
323 LogInfo("current page is raised");
324 // set only encoded bundle
325 double scale = elm_config_scale_get();
326 PluginModuleSupport::setCustomProperties(
329 ApplicationDataSingleton::Instance().getEncodedBundle());
330 PluginModuleSupport::dispatchJavaScriptEvent(
332 WrtPlugins::W3C::ServiceCustomEvent,
335 LogInfo("service page is loaded");
336 m_currentUri = DPL::ToUTF8String(*servicedUri);
337 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
339 elm_win_raise(m_window);
340 evas_object_focus_set(m_currentEwkView, EINA_TRUE);
343 // call user callback
344 if (!m_cbs->reset.empty()) {
347 if (!m_cbs->bufferSet.empty()) {
348 m_cbs->bufferSet(m_currentEwkView);
352 void ViewLogic::backward()
354 if (ewk_view_back_possible(m_currentEwkView)) {
355 ewk_view_back(m_currentEwkView);
357 if (1 >= m_ewkViewList.size()) {
358 // If there is no previous page, widget move to backgroud.
359 LogInfo("Widget move to backgroud");
360 elm_win_lower(m_window);
362 // Back to previous webview
363 LogInfo("Widget move to previous webview");
364 ecore_idler_add(windowCloseIdlerCallback, this);
369 void ViewLogic::reload()
371 ewk_view_reload(m_currentEwkView);
374 void ViewLogic::forward()
376 if (ewk_view_forward_possible(m_currentEwkView)) {
377 ewk_view_forward(m_currentEwkView);
381 void ViewLogic::reloadStartPage()
383 LogInfo("Reload Start Page");
385 if (m_ewkViewList.size() == 0) {
386 // create new webview
387 createEwkView(evas_object_evas_get(m_window));
388 ewkClientInit(m_currentEwkView);
390 // close opened windows
391 while (m_ewkViewList.size() > 1) {
392 if (!m_cbs->bufferUnset.empty()) {
393 m_cbs->bufferUnset(m_currentEwkView);
395 removeEwkView(m_currentEwkView);
396 m_currentEwkView = m_ewkViewList.back();
398 LogInfo("Close ewkViews done : m_ewkViewList.size() = "
399 << m_ewkViewList.size());
403 prepareEwkView(m_currentEwkView);
404 initializePluginLoading();
407 ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
410 if (!m_cbs->bufferSet.empty()) {
411 m_cbs->bufferSet(m_currentEwkView);
413 LogInfo("Reloading Start Page is done!");
416 Evas_Object* ViewLogic::getCurrentWebview()
418 LogInfo("get current webview");
419 return m_currentEwkView;
422 void ViewLogic::fireJavascriptEvent(int event, void* data)
424 PluginModuleSupport::dispatchJavaScriptEvent(
426 static_cast<WrtPlugins::W3C::CustomEventType>(event),
430 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
435 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
437 LogInfo("initializeEwkContext called");
438 Assert(newEwkContext && "Ewk_Context provided can not be null");
439 // bundle callback setting
440 ewk_context_message_from_injected_bundle_callback_set(
442 contextMessageFromInjectedBundleCallback,
443 static_cast<void*>(this));
445 // proxy server setting
446 char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
447 if ((!proxyAddress) || (strlen(proxyAddress) == 0)
448 || (strstr(proxyAddress, "0.0.0.0")))
450 LogInfo("proxy address is empty");
451 ewk_context_proxy_uri_set(newEwkContext, NULL);
453 LogInfo("proxy address [" << proxyAddress << "]");
454 ewk_context_proxy_uri_set(newEwkContext, proxyAddress);
463 const char *theme = elm_theme_get(NULL);
466 LogInfo("theme is " << m_theme);
469 // Ewk download callback (WKContextDownloadClient)
470 ewk_context_did_start_download_callback_set(
472 didStartDownloadCallback,
475 // set to member value
476 m_ewkContext = newEwkContext;
479 void ViewLogic::finalizeEwkContext()
481 LogInfo("finalizeEwkContext called");
482 ewk_context_message_from_injected_bundle_callback_set(
486 // ewk_context_delete(m_ewkContext);
490 void ViewLogic::initializeSupport()
492 // set local stroage database path
493 WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
494 ewk_context_web_storage_path_set(m_ewkContext,
495 dao.getPrivateLocalStoragePath().c_str());
496 m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
497 ViewModule::StorageSupport::initializeStorage(m_model);
498 m_appsSupport->initialize(m_model);
499 m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
502 // m_vibrationSupport->initialize();
505 void ViewLogic::initializePluginLoading()
507 // inform wrt information for plugin loading to web process
508 PluginModuleSupport::start(
511 elm_config_scale_get(),
512 ApplicationDataSingleton::Instance().getEncodedBundle(),
514 m_model->SettingList.Get().isEncrypted());
517 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
518 Assert(NULL != wkView && "ewk_view not created at this point");
519 // WKPageLoaderClient
520 evas_object_smart_callback_add(
525 evas_object_smart_callback_add(
528 loadFinishedCallback,
530 evas_object_smart_callback_add(
533 titleChangedCallback,
535 evas_object_smart_callback_add(
538 loadProgressCallback,
540 evas_object_smart_callback_add(
542 EWK_LOAD_PROGRESS_FINISHED,
543 loadProgressFinishedCallback,
545 evas_object_smart_callback_add(
548 processCrashedCallback,
552 evas_object_smart_callback_add(
555 createWindowCallback,
557 evas_object_smart_callback_add(
563 // WKPagePolicyClient
564 evas_object_smart_callback_add(
566 EWK_POLICY_NAVIGATION_DECIDE,
567 policyNavigationDecideCallback,
569 evas_object_smart_callback_add(
571 EWK_POLICY_NEWWINDOW_DECIDE,
572 policyNewWindowDecideCallback,
574 evas_object_smart_callback_add(
576 EWK_POLICY_RESPONSE_DECIDE,
577 pageResponseDecideCallback,
580 // WKPageContextMenuClient
581 evas_object_smart_callback_add(
583 EWK_CONTEXTMENU_CUSTOMIZE,
584 contextmenuCustomizeCallback,
588 evas_object_smart_callback_add(
594 // EWK Geolocation Callback
595 evas_object_smart_callback_add(
597 EWK_REQUEST_GEOLOCATION_PERMISSION,
598 geolocationPermissionRequestCallback,
601 // EWK Notification Callback
602 evas_object_smart_callback_add(
604 EWK_NOTIFICATION_SHOW,
605 notificationShowCallback,
607 evas_object_smart_callback_add(
609 EWK_NOTIFICATION_CANCEL,
610 notificationCancelCallback,
612 evas_object_smart_callback_add(
614 EWK_NOTIFICATION_PERMISSION_REQUEST,
615 notificationPermissionRequestCallback,
618 // EWK Vibration Callback
619 evas_object_smart_callback_add(
621 EWK_VIBRATION_VIBRATE,
622 vibrationVibrateCallback,
624 evas_object_smart_callback_add(
626 EWK_VIBRATION_CANCEL,
627 vibrationCancelCallback,
629 evas_object_smart_callback_add(
631 EWK_CONTEXT_EXCEEDED_QUOATA,
632 databaseUsagePermissionRequestCallback,
634 evas_object_smart_callback_add(
636 EWK_FILESYSTEM_PERMISSION_REQUEST,
637 fileSystemPermissionRequestCallback,
640 // EWK Orientation Callback
641 //ewk_view_orientation_lock_callback_set(
643 // orientationLockCallback,
646 // Fullscreen API callbacks
647 evas_object_smart_callback_add(
649 EWK_FULLSCREEN_ENTER,
650 enterFullscreenCallback,
652 evas_object_smart_callback_add(
655 exitFullscreenCallback,
659 // when ime start to be showed on the webview,
660 // this callback will be called
661 evas_object_smart_callback_add(
663 EWK_INPUTMETHOD_CHANGED,
667 // this callback will be called
668 // when ime finishes to be showed on the webview
669 // "event_info" arg of this callback is always NULL point
670 // if web content should know size of ime,
671 // use "inputmethod,changed" instead of this.
673 evas_object_smart_callback_add(
675 EWK_EDITORCLIENT_IME_OPENED,
679 // when ime finished to be hidden,
680 // this callback will be called
681 evas_object_smart_callback_add(
683 EWK_EDITORCLIENT_IME_CLOSED,
687 // custom content/scheme handlers
688 evas_object_smart_callback_add(
690 EWK_PROTOCOLHANDLER_REGISTRATION,
691 protocolHandlerRegistrationCallback,
693 evas_object_smart_callback_add(
695 EWK_PROTOCOLHANDLER_ISREGISTERED,
696 protocolHandlerIsRegisteredCallback,
698 evas_object_smart_callback_add(
700 EWK_PROTOCOLHANDLER_UNREGISTRATION,
701 protocolHandlerUnregistrationCallback,
704 evas_object_smart_callback_add(
706 EWK_CONTENTHANDLER_REGISTRATION,
707 contentHandlerRegistrationCallback,
709 evas_object_smart_callback_add(
711 EWK_CONTENTHANDLER_ISREGISTERED,
712 contentHandlerIsRegisteredCallback,
714 evas_object_smart_callback_add(
716 EWK_CONTENTHANDLER_UNREGISTRATION,
717 contentHandlerUnregistrationCallback,
721 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
722 LogDebug("ewkClientDeinit");
723 Assert(NULL != wkView && "ewk_view not created at this point");
725 // WKPageLoaderClient
726 evas_object_smart_callback_del(
729 loadStartedCallback);
730 evas_object_smart_callback_del(
733 loadFinishedCallback);
734 evas_object_smart_callback_del(
737 titleChangedCallback);
738 evas_object_smart_callback_del(
741 loadProgressCallback);
742 evas_object_smart_callback_del(
744 EWK_LOAD_PROGRESS_FINISHED,
745 loadProgressFinishedCallback);
746 evas_object_smart_callback_del(
749 loadProgressCallback);
752 evas_object_smart_callback_del(
755 createWindowCallback);
756 evas_object_smart_callback_del(
759 closeWindowCallback);
761 // WKPagePolicyClient
762 evas_object_smart_callback_del(
764 EWK_POLICY_NAVIGATION_DECIDE,
765 policyNavigationDecideCallback);
766 evas_object_smart_callback_del(
768 EWK_POLICY_NEWWINDOW_DECIDE,
769 policyNewWindowDecideCallback);
770 evas_object_smart_callback_del(
772 EWK_POLICY_RESPONSE_DECIDE,
773 pageResponseDecideCallback);
775 // WKPageContextMenuClient
776 evas_object_smart_callback_del(
778 EWK_CONTEXTMENU_CUSTOMIZE,
779 contextmenuCustomizeCallback);
782 evas_object_smart_callback_del(
787 // EWK Geolocation Callback
788 evas_object_smart_callback_del(
790 EWK_REQUEST_GEOLOCATION_PERMISSION,
791 geolocationPermissionRequestCallback);
793 // EWK Notification Callback
794 evas_object_smart_callback_del(
796 EWK_NOTIFICATION_SHOW,
797 notificationShowCallback);
798 evas_object_smart_callback_del(
800 EWK_NOTIFICATION_CANCEL,
801 notificationCancelCallback);
802 evas_object_smart_callback_del(
804 EWK_NOTIFICATION_PERMISSION_REQUEST,
805 notificationPermissionRequestCallback);
807 // EWK Vibration Callback
808 evas_object_smart_callback_del(
810 EWK_VIBRATION_VIBRATE,
811 vibrationVibrateCallback);
812 evas_object_smart_callback_del(
814 EWK_VIBRATION_CANCEL,
815 vibrationCancelCallback);
817 evas_object_smart_callback_del(
819 EWK_CONTEXT_EXCEEDED_QUOATA,
820 databaseUsagePermissionRequestCallback);
821 evas_object_smart_callback_del(
823 EWK_FILESYSTEM_PERMISSION_REQUEST,
824 fileSystemPermissionRequestCallback);
826 // EWK Orientation Callback
827 //ewk_view_orientation_lock_callback_set(
832 // ime change/show/hide callback
833 evas_object_smart_callback_del(
835 EWK_INPUTMETHOD_CHANGED,
837 evas_object_smart_callback_del(
839 EWK_EDITORCLIENT_IME_OPENED,
841 evas_object_smart_callback_del(
843 EWK_EDITORCLIENT_IME_CLOSED,
846 // custom content/scheme handlers
847 evas_object_smart_callback_del(
849 EWK_PROTOCOLHANDLER_REGISTRATION,
850 protocolHandlerRegistrationCallback);
851 evas_object_smart_callback_del(
853 EWK_PROTOCOLHANDLER_ISREGISTERED,
854 protocolHandlerIsRegisteredCallback);
855 evas_object_smart_callback_del(
857 EWK_PROTOCOLHANDLER_UNREGISTRATION,
858 protocolHandlerUnregistrationCallback);
860 evas_object_smart_callback_del(
862 EWK_CONTENTHANDLER_REGISTRATION,
863 contentHandlerRegistrationCallback);
864 evas_object_smart_callback_del(
866 EWK_CONTENTHANDLER_ISREGISTERED,
867 contentHandlerIsRegisteredCallback);
868 evas_object_smart_callback_del(
870 EWK_CONTENTHANDLER_UNREGISTRATION,
871 contentHandlerUnregistrationCallback);
874 void ViewLogic::createEwkView(Evas* canvas)
876 LogDebug("createEwkVeiw");
878 ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
879 Evas_Object* newEwkView = ewk_view_add_with_context(
882 ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
885 LogError("WKView creation failed");
890 // even arguments pass the ewkContext, this API should be called
891 // after webkit Evas_Object is created
892 Ewk_Cookie_Manager *ewkCookieManager;
894 ewk_context_cookie_manager_get(m_ewkContext);
895 ewk_cookie_manager_accept_policy_set(ewkCookieManager,
896 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
898 LogInfo("push webview: " << newEwkView);
899 m_ewkViewList.push_back(newEwkView);
900 m_currentEwkView = newEwkView;
903 void ViewLogic::setStartPage()
905 /* Start URI (as other uris) is now localized
906 * on WebProcess side */
907 m_currentUri = m_startUrl;
910 void ViewLogic::prepareEwkView(Evas_Object *wkView)
912 LogDebug("prepareEwkView called");
914 Ewk_Settings* settings = ewk_view_settings_get(wkView);
917 auto userAgentString =
918 ViewModule::UserAgentSupport::getUserAgentFromVconf();
919 if (!userAgentString.empty()) {
920 LogDebug("Setting custom user agent as: " << userAgentString);
921 ewk_view_user_agent_set(wkView, userAgentString.c_str());
924 // set custom header : language
925 using namespace ViewModule::CustomHeaderSupport;
926 std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
927 if (!customHeaderString.empty()) {
928 LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
929 LogDebug("custom value=[" << customHeaderString << "]");
930 ewk_view_custom_header_add(wkView,
931 ACCEPT_LANGUAGE.c_str(),
932 customHeaderString.c_str());
935 // webkit NPAPI plugins is always on in wrt
936 ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
938 // The followings are not implemeted yet by webkit2
939 // ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
940 // ewk_view_mode_set();
941 // ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
942 // ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
943 // ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
944 // elm_webview_show_magnifier_set(EINA_FALSE);
945 ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
946 ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
947 ewk_settings_auto_fitting_set(settings, EINA_TRUE);
949 // disable zoom option when user click the input field
950 // this option is useful with the normal website
951 // for the make user friendly, disable auto zoom in the webapp
952 // The followings are not implemeted yet by webkit2
953 // elm_webview_input_field_zoom_set(EINA_FALSE);
955 // set cookie database path
956 // The followings are not implemeted yet by webkit2
957 // ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
959 // set visibility to WebCore. This value will be used for html5.
960 // also, this value will be changed in the suspend, resume
961 // or create window, close window.
962 ewk_view_page_visibility_state_set(wkView,
963 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
967 void ViewLogic::removeEwkView(Evas_Object *wkView)
969 LogInfo("removeEwkView called");
971 Assert(0 != m_ewkViewList.size());
973 // unregister webview callbacks
974 ewkClientDeinit(wkView);
976 // suspend NPAPI plugin - Not implemented by Webkit2
977 // ewk_view_pause_or_resume_plugins();
978 evas_object_del(wkView);
979 m_ewkViewList.remove(wkView);
982 void ViewLogic::resumeEwkView(Evas_Object *wkView)
984 LogInfo("resumeEwkView called");
987 // register webview callback
988 ewkClientInit(wkView);
991 resumeWebkit(wkView);
996 void ViewLogic::suspendEwkView(Evas_Object *wkView)
998 LogInfo("suspendEwkView called");
1002 suspendWebkit(wkView);
1004 // unregister webview callbacks
1005 ewkClientDeinit(wkView);
1010 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1012 LogDebug("resumeWebkit");
1015 // resume NPAPI plugin
1016 // The followings are not implemeted yet by webkit2
1017 // ewk_view_pause_or_resume_plugins(false);
1018 // ewk_view_pause_or_resume_video_audio(false);
1019 // ewk_view_javascript_resume();
1020 // ewk_view_enable_render();
1021 // ewk_view_reduce_plugins_frame_rate(false);
1022 ewk_view_resume(wkView);
1023 ewk_view_visibility_set(wkView, EINA_TRUE);
1024 ewk_view_page_visibility_state_set(wkView,
1025 EWK_PAGE_VISIBILITY_STATE_VISIBLE,
1030 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1032 LogDebug("suspendWebkit");
1035 // suspend the followings
1036 // The followings are not implemeted yet by webkit2
1037 // ewk_view_pause_or_resume_plugins(true);
1038 // ewk_view_pause_or_resume_video_audio(true);
1040 // send visibility event to webpage
1041 ewk_view_page_visibility_state_set(wkView,
1042 EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1044 ewk_view_suspend(wkView);
1045 ewk_view_visibility_set(wkView, EINA_FALSE);
1049 void ViewLogic::contextMessageFromInjectedBundleCallback(
1055 LogDebug("contextMessageFromInjectedBundleCallback called");
1057 ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1058 // didRecieveMessageFromInjectedBundleCallback - returnData is null
1059 // didReceiveSynchronousMessageCallback - returnData isn't null
1060 // WKContextInjectedBundleClient bundleClient = {
1061 // kWKContextInjectedBundleClientCurrentVersion,
1062 // static_cast<void*>(this),
1063 // &didRecieveMessageFromInjectedBundleCallback,
1064 // &didReceiveSynchronousMessageCallback
1066 if (NULL == returnData) {
1067 This->didRecieveMessageFromInjectedBundle(name, body);
1069 This->didReceiveSynchronousMessage(name, body, returnData);
1073 void ViewLogic::didStartDownloadCallback(
1074 const char* downloadUrl,
1077 LogDebug("didStartDownloadCallback called");
1079 ViewLogic* This = static_cast<ViewLogic*>(data);
1080 Assert(downloadUrl);
1081 LogDebug("download url = " << downloadUrl);
1082 This->m_appsSupport->downloadRequest(
1088 void ViewLogic::loadStartedCallback(
1091 void* /*eventInfo*/)
1093 LogDebug("loadStartedCallback called");
1095 ViewLogic* This = static_cast<ViewLogic*>(data);
1096 evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1098 // call loadFinish callback to wrt-client
1099 if (!This->m_cbs->loadStart.empty()) {
1100 This->m_cbs->loadStart(obj);
1105 void ViewLogic::loadFinishedCallback(
1108 void* /*eventInfo*/)
1110 LogDebug("loadFinishedCallback called");
1112 ViewLogic* This = static_cast<ViewLogic*>(data);
1115 const char* url = ewk_view_url_get(This->m_currentEwkView);
1116 if (NULL == url || strlen(url) == 0) {
1117 LogError("url is empty");
1119 DPL::OptionalString jsOptionalString =
1120 ViewModule::PasswordSupport::jsForAutoFillData(url);
1121 if (jsOptionalString.IsNull()) {
1122 LogError("Fail to get JS String");
1124 std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1126 if(EINA_FALSE == ewk_view_script_execute(
1127 This->m_currentEwkView,
1129 didRunJavaScriptCallback,
1132 LogError("JS for auto fill data failed.");
1137 // call loadFinish callback to wrt-client
1138 if (!This->m_cbs->loadFinish.empty()) {
1139 This->m_cbs->loadFinish(obj);
1142 // set only encoded bundle
1143 double scale = elm_config_scale_get();
1144 PluginModuleSupport::setCustomProperties(
1147 ApplicationDataSingleton::Instance().getEncodedBundle());
1148 // check if 'appsevice' event is registed at the current frames.
1149 // If so, dispatch the event to frames.
1150 PluginModuleSupport::dispatchJavaScriptEvent(
1152 WrtPlugins::W3C::ServiceCustomEvent,
1156 void ViewLogic::titleChangedCallback(
1158 Evas_Object* /*obj*/,
1161 LogDebug("titleChangedCallback called");
1163 ViewLogic* This = static_cast<ViewLogic*>(data);
1165 const char* title = static_cast<char*>(eventInfo);
1167 if (0 == strlen(title)) {
1168 LogDebug("title data is empty");
1171 LogDebug("Title = [" << title << "]");
1172 This->m_schemeSupport->HandleTizenScheme(title,
1174 This->m_currentEwkView);
1177 void ViewLogic::loadProgressCallback(
1179 Evas_Object* /*obj*/,
1182 double* progress = static_cast<double*>(eventInfo);
1183 LogDebug("didChangeProgressCallback progress = " << *progress);
1186 void ViewLogic::loadProgressFinishedCallback(
1188 Evas_Object* /*obj*/,
1189 void* /*eventInfo*/)
1191 LogDebug("didFinishProgressCallback");
1193 ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1194 if (!view->m_cbs->progressFinish.empty()) {
1195 view->m_cbs->progressFinish();
1199 void ViewLogic::processCrashedCallback(
1201 Evas_Object* /*obj*/,
1204 LogInfo("processCrashedCallback");
1206 ViewLogic const * const view =
1207 static_cast<ViewLogic const * const>(data);
1208 if (!view->m_cbs->webCrash.empty()) {
1209 view->m_cbs->webCrash();
1211 // This flag will be prevented exit() call in the Webkit side
1212 if (NULL != eventInfo) {
1213 *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1217 void ViewLogic::createWindowCallback(
1222 LogDebug("createWindowCallback");
1224 ViewLogic* This = static_cast<ViewLogic*>(data);
1226 // First, current webview should be handled by user callback
1227 if (!This->m_cbs->bufferUnset.empty()) {
1228 This->m_cbs->bufferUnset(obj);
1231 // this can be set by executable for specific purpose
1232 Evas* canvas = NULL;
1233 if (!This->m_cbs->windowCreateBefore.empty()) {
1234 // 'obj' is parent webview object
1235 This->m_cbs->windowCreateBefore(&canvas, obj);
1238 canvas = evas_object_evas_get(This->m_window);
1241 // create new ewkview
1242 This->createEwkView(canvas);
1243 Evas_Object* newEwkView = This->m_currentEwkView;
1245 // initialize new ewkview
1246 This->setStartPage();
1247 This->ewkClientInit(newEwkView);
1248 This->prepareEwkView(newEwkView);
1250 // Specific jobs of child, parent webview are handled by each executable
1251 if (!This->m_cbs->windowCreateAfter.empty()) {
1252 // 'obj' is parent webview, 'newEwkView' is child webview
1253 This->m_cbs->windowCreateAfter(obj, newEwkView);
1256 // Lastly, new webview should be handled by user callback
1257 if (!This->m_cbs->bufferSet.empty()) {
1258 This->m_cbs->bufferSet(newEwkView);
1260 *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1263 void ViewLogic::closeWindowCallback(
1266 void* /*eventInfo*/)
1268 LogDebug("closeWindowCallback");
1269 ViewLogic* This = static_cast<ViewLogic*>(data);
1270 This->m_closedEwkView = obj;
1271 ecore_idler_add(windowCloseIdlerCallback, This);
1274 void ViewLogic::policyNavigationDecideCallback(
1276 Evas_Object* /*obj*/,
1279 LogDebug("policyNavigationDecideCallback called");
1281 ViewLogic* This = static_cast<ViewLogic*>(data);
1283 Ewk_Policy_Decision* policyDecision =
1284 static_cast<Ewk_Policy_Decision*>(eventInfo);
1286 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1290 This->m_currentEwkView))
1293 ewk_policy_decision_use(policyDecision);
1295 // check whether this is new empty window
1296 const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1297 if(!activeUrl || 0 == strlen(activeUrl)) {
1299 * The view is empty and scheme has been handled externally. When
1300 * user gets back from the external application he'd see blank page
1301 * and won't be able to navigate back. This happens when window.open
1302 * is used to handle schemes like sms/mms/mailto (for example in
1303 * WAC web standards tests: WS-15XX).
1305 * To solve the problem, the empty view is removed from the stack
1306 * and the previous one is shown. This is not an elegant solution
1307 * but we don't have a better one.
1309 LogInfo("Scheme has been handled externally. Removing empty view.");
1310 if (ewk_view_back_possible(This->m_currentEwkView)) {
1311 // go back to previous WKPage
1312 ewk_view_back(This->m_currentEwkView);
1314 // stop current WKPage
1315 ewk_view_stop(This->m_currentEwkView);
1316 ecore_idler_add(windowCloseIdlerCallback, This);
1321 ewk_policy_decision_ignore(policyDecision);
1325 void ViewLogic::policyNewWindowDecideCallback(
1327 Evas_Object* /*obj*/,
1330 LogDebug("policyNewWindowDecideCallback called");
1332 ViewLogic* This = static_cast<ViewLogic*>(data);
1334 Ewk_Policy_Decision* policyDecision =
1335 static_cast<Ewk_Policy_Decision*>(eventInfo);
1337 if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1341 This->m_currentEwkView))
1343 ewk_policy_decision_use(policyDecision);
1346 ewk_policy_decision_ignore(policyDecision);
1350 void ViewLogic::pageResponseDecideCallback(
1352 Evas_Object* /*obj*/,
1355 LogDebug("pageResponseDecideCallback called");
1357 ViewLogic* This = static_cast<ViewLogic*>(data);
1359 Ewk_Policy_Decision* policyDecision =
1360 static_cast<Ewk_Policy_Decision*>(eventInfo);
1361 Ewk_Policy_Decision_Type policyDecisionType =
1362 ewk_policy_decision_type_get(policyDecision);
1364 if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1366 ewk_policy_decision_use(policyDecision);
1367 } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1368 LogDebug("download");
1369 ewk_policy_decision_suspend(policyDecision);
1371 // get uri information
1372 const char* url = ewk_policy_decision_url_get(policyDecision);
1373 if (NULL == url || strlen(url) == 0) {
1374 LogDebug("url data is empty");
1375 ewk_policy_decision_use(policyDecision);
1378 LogDebug("url = [" << url << "]");
1380 // get content information
1381 const char* content =
1382 ewk_policy_decision_response_mime_get(policyDecision);
1383 LogDebug("content type = [" << content << "]");
1385 // get cookie information
1386 const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1387 LogDebug("cookie = [" << cookie << "]");
1389 LogDebug("Content not supported, will be opened in external app");
1390 This->m_appsSupport->downloadRequest(
1394 ewk_policy_decision_ignore(policyDecision);
1395 } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1397 ewk_policy_decision_ignore(policyDecision);
1399 LogDebug("Type isn't handled");
1400 ewk_policy_decision_ignore(policyDecision);
1404 void ViewLogic::contextmenuCustomizeCallback(
1406 Evas_Object* /*obj*/,
1409 LogDebug("contextmenuCustomizeCallback called");
1412 ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1413 Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1414 if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1415 (This->m_model->SettingList.Get().getContextMenu()
1416 == ContextMenu_Disable))
1418 LogDebug("ContextMenu Disable!!");
1419 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1420 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1422 ewk_context_menu_item_remove(menu, item);
1425 LogDebug("ContextMenu Enable!!");
1426 for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1427 Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1429 Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1432 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1433 ewk_context_menu_item_remove(menu, item);
1436 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1437 ewk_context_menu_item_remove(menu, item);
1448 void ViewLogic::formSubmitCallback(
1450 Evas_Object* /*obj*/,
1453 LogDebug("formSubmitCallback called");
1455 Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1457 const char* uri = ewk_form_data_url_get(formData);
1459 LogError("URL is empty");
1463 Eina_Hash* userData = ewk_form_data_values_get(formData);
1464 ViewModule::PasswordSupport::submitClicked(uri, userData);
1467 void ViewLogic::geolocationPermissionRequestCallback(
1469 Evas_Object* /*obj*/,
1473 ViewLogic* This = static_cast<ViewLogic*>(data);
1475 ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1477 This->m_securityOriginSupport->getSecurityOriginDAO(),
1481 void ViewLogic::notificationShowCallback(
1483 Evas_Object* /*obj*/,
1486 LogDebug("notificationShowCallback called");
1488 ViewLogic* This = static_cast<ViewLogic*>(data);
1491 Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1493 using namespace ViewModule::WebNotification;
1495 WebNotificationDataPtr notiData(
1496 new WebNotificationData(
1498 ewk_notification_id_get(noti)));
1500 DPL::OptionalString string =
1501 DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1502 if (!string.IsNull()) {
1503 notiData->m_iconURL = DPL::ToUTF8String(*string);
1505 string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1506 if (!string.IsNull()) {
1507 notiData->m_title = DPL::ToUTF8String(*string);
1509 string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1510 if (!string.IsNull()) {
1511 notiData->m_body = DPL::ToUTF8String(*string);
1514 LogInfo("notification id : " << notiData->m_id);
1515 LogInfo("notification iconURL : " << notiData->m_iconURL);
1516 LogInfo("notification title : " << notiData->m_title);
1517 LogInfo("notification body : " << notiData->m_body);
1519 showWebNotification(notiData);
1520 ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1523 void ViewLogic::notificationCancelCallback(
1525 Evas_Object* /*obj*/,
1526 void* /*eventInfo*/)
1528 LogDebug("notificationCancelCallback called");
1531 void ViewLogic::notificationPermissionRequestCallback(
1533 Evas_Object* /*obj*/,
1536 LogDebug("notificationPermissionRequestCallback called");
1538 ViewLogic* This = static_cast<ViewLogic*>(data);
1541 Ewk_Notification_Permission_Request* request =
1542 static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1543 ewk_notification_permission_request_response(
1550 void ViewLogic::vibrationVibrateCallback(
1552 Evas_Object* /*obj*/,
1555 LogDebug("vibrationVibrateCallback called");
1557 ViewLogic* This = static_cast<ViewLogic*>(data);
1560 const long vibrationTime = *(static_cast<const long*>(eventInfo));
1563 // This->m_vibrationSupport->startVibration(vibrationTime);
1568 void ViewLogic::vibrationCancelCallback(
1570 Evas_Object* /*obj*/,
1571 void* /*eventInfo*/)
1573 LogDebug("vibrationCancelCallback called");
1575 ViewLogic* This = static_cast<ViewLogic*>(data);
1578 // This->m_vibrationSupport->stopVibration();
1583 // EWK Orientation Callback
1584 Eina_Bool ViewLogic::orientationLockCallback(
1586 Eina_Bool /*needLock*/,
1590 LogDebug("orientationLockCallback called");
1592 ViewLogic* This = static_cast<ViewLogic*>(data);
1594 if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1595 LogDebug("orientation is portrait-primary");
1596 elm_win_rotation_with_resize_set(This->m_window, 0);
1597 ewk_view_orientation_send(obj, 0);
1598 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1599 LogDebug("orientation is landscape-primary");
1600 elm_win_rotation_with_resize_set(This->m_window, 270);
1601 ewk_view_orientation_send(obj, 90);
1602 } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1603 LogDebug("orientation is portrait-secondary");
1604 elm_win_rotation_with_resize_set(This->m_window, 180);
1605 ewk_view_orientation_send(obj, 180);
1606 } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1607 LogDebug("orientation is landscape-secondary");
1608 elm_win_rotation_with_resize_set(This->m_window, 90);
1609 ewk_view_orientation_send(obj, -90);
1611 LogDebug("Wrong orientation is set");
1618 // Fullscreen API callbacks
1619 void ViewLogic::enterFullscreenCallback(
1621 Evas_Object* /*obj*/,
1622 void* /*eventInfo*/)
1624 LogInfo("enterFullscreenCallback called");
1626 ViewLogic* This = static_cast<ViewLogic*>(data);
1627 if (!This->m_cbs->toggleFullscreen.empty()) {
1628 This->m_cbs->toggleFullscreen(true);
1631 void ViewLogic::exitFullscreenCallback(
1633 Evas_Object* /*obj*/,
1634 void* /*eventInfo*/)
1636 LogInfo("exitFullscreenCallback called");
1638 ViewLogic* This = static_cast<ViewLogic*>(data);
1639 if (!This->m_cbs->toggleFullscreen.empty()) {
1640 This->m_cbs->toggleFullscreen(false);
1644 void ViewLogic::imeChangedCallback(
1646 Evas_Object* /*obj*/,
1652 ViewLogic* This = static_cast<ViewLogic*>(data);
1653 Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1654 This->m_imeWidth = rect->w;
1655 This->m_imeHeight = rect->h;
1658 void ViewLogic::imeOpenedCallback(
1660 Evas_Object* /*obj*/,
1661 void* /*eventInfo*/)
1665 ViewLogic* This = static_cast<ViewLogic*>(data);
1667 using namespace WrtPlugins::W3C;
1668 SoftKeyboardChangeArgs args;
1669 args.state = IME_STATE_ON;
1670 args.width = This->m_imeWidth;
1671 args.height = This->m_imeHeight;
1672 This->fireJavascriptEvent(
1673 static_cast<int>(SoftKeyboardChangeCustomEvent),
1677 void ViewLogic::imeClosedCallback(
1679 Evas_Object* /*obj*/,
1680 void* /*eventInfo*/)
1684 ViewLogic* This = static_cast<ViewLogic*>(data);
1686 using namespace WrtPlugins::W3C;
1687 SoftKeyboardChangeArgs args;
1688 args.state = IME_STATE_OFF;
1690 This->fireJavascriptEvent(
1691 static_cast<int>(SoftKeyboardChangeCustomEvent),
1696 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1699 Ewk_Custom_Handlers_Data* handler =
1700 static_cast<Ewk_Custom_Handlers_Data*>(data);
1701 CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1702 const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1704 LogDebug("base url: " << base_url);
1705 customHandler->base_url = DPL::FromASCIIString(string(base_url));
1707 const char* url = ewk_custom_handlers_data_url_get(handler);
1709 LogDebug("url: " << url);
1710 customHandler->url = DPL::FromASCIIString(string(url));
1712 const char* target = ewk_custom_handlers_data_target_get(handler);
1714 LogDebug("target: " << target);
1715 customHandler->target = DPL::FromASCIIString(string(target));
1717 const char* title = ewk_custom_handlers_data_title_get(handler);
1719 LogDebug("title: " << title);
1720 customHandler->title = DPL::FromASCIIString(string(title));
1722 return customHandler;
1725 void ViewLogic::attachToCustomHandlersDao()
1727 if (!m_attachedToCustomHandlerDao) {
1728 CustomHandlerDB::Interface::attachDatabaseRW();
1732 void ViewLogic::detachFromCustomHandlersDao()
1734 if (m_attachedToCustomHandlerDao) {
1735 CustomHandlerDB::Interface::detachDatabase();
1739 const int protocolWhiteListLenth = 15;
1740 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1758 const int contentBlackListLenth = 14;
1759 char const * const contentBlackList[contentBlackListLenth] = {
1760 "application/x-www-form-urlencoded",
1761 "application/xhtml+xml",
1767 "multipart/x-mixed-replace",
1768 "text/cache-manifest",
1776 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1782 CustomHandlerDB::CustomHandlerPtr customHandler =
1783 getCustomHandlerFromData(eventInfo);
1785 std::string scheme = DPL::ToUTF8String(customHandler->target);
1786 if (scheme.empty()) {
1787 LogError("No scheme provided");
1788 //TODO what about securityError?
1791 bool matched = false;
1792 //scheme on whiteList
1793 for (int i = 0; i < protocolWhiteListLenth; ++i) {
1794 if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1796 LogDebug("Match found, protocol can be handled");
1801 //starts with web+ and have at least 5 chars (lowercase ASCII)
1802 if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1803 LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1804 //throw SecurityException
1811 if (c < 'a' || c > 'z') {
1812 LogWarning("Wrong char inside scheme. "
1813 << "Only lowercase ASCII letters accepted");
1814 //throw SecurityException
1821 ViewLogic* This = static_cast<ViewLogic*>(data);
1822 LogDebug("Creating handlers dao");
1823 This->attachToCustomHandlersDao();
1824 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1825 CustomHandlerDB::CustomHandlerPtr handler =
1826 handlersDao.getProtocolHandler(customHandler->target, customHandler->url);
1828 LogDebug("Protocol already registered - nothing to do");
1830 LogDebug("Protocol handler not found");
1831 if (Wrt::Popup::PopupInvoker().askYesNo(PROTOCOL_HANDLER_ASK_TITLE, PROTOCOL_HANDLER_ASK_MSG)) {
1832 LogDebug("User allowed");
1833 customHandler->user_allowed = true;
1835 LogDebug("User didn't allow");
1836 customHandler->user_allowed = false;
1838 handlersDao.registerProtocolHandler(*(customHandler.get()));
1839 LogDebug("Protocal saved");
1842 // TODO to be continued...
1845 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1850 getCustomHandlerFromData(eventInfo);
1851 // TODO to be continued...
1854 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1859 getCustomHandlerFromData(eventInfo);
1860 // TODO to be continued...
1863 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1869 CustomHandlerDB::CustomHandlerPtr customHandler =
1870 getCustomHandlerFromData(eventInfo);
1872 std::string mimeType = DPL::ToUTF8String(customHandler->target);
1873 if (mimeType.empty()) {
1874 LogError("No mimeType provided.");
1877 for (int i = 0; i < contentBlackListLenth; ++i)
1879 if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1881 LogWarning("mimeType blacklisted");
1882 //throw SecurityException
1887 ViewLogic* This = static_cast<ViewLogic*>(data);
1888 LogDebug("Creating handlers dao");
1889 This->attachToCustomHandlersDao();
1890 CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1891 CustomHandlerDB::CustomHandlerPtr handler =
1892 handlersDao.getContentHandler(customHandler->target, customHandler->url);
1894 LogDebug("Content already registered - nothing to do");
1896 LogDebug("Content handler not found");
1897 if (Wrt::Popup::PopupInvoker().askYesNo(CONTENT_HANDLER_ASK_TITLE, CONTENT_HANDLER_ASK_MSG)) {
1898 LogDebug("User allowed");
1899 customHandler->user_allowed = true;
1901 LogDebug("User didn't allow");
1902 customHandler->user_allowed = false;
1904 handlersDao.registerContentHandler(*(customHandler.get()));
1905 LogDebug("Content saved");
1908 // TODO to be continued...
1911 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
1916 getCustomHandlerFromData(eventInfo);
1917 // TODO to be continued...
1920 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
1925 getCustomHandlerFromData(eventInfo);
1926 // TODO to be continued...
1929 void ViewLogic::didRunJavaScriptCallback(
1930 Evas_Object* /*obj*/,
1934 LogInfo("didRunJavaScriptCallback called");
1935 LogInfo("result = " << result);
1938 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1940 LogDebug("closeIdlerCallback");
1941 ViewLogic* This = static_cast<ViewLogic*>(data);
1942 This->windowClose();
1943 return ECORE_CALLBACK_CANCEL;
1946 int ViewLogic::appcoreLowMemoryCallback(void *data)
1948 LogInfo("appcoreLowMemoryCallback");
1950 ViewLogic* This = static_cast<ViewLogic*>(data);
1952 if (NULL == This->m_ewkContext) {
1953 LogInfo("ewk isn't initialize at this moment");
1955 // Crash may occur on specific situation
1956 // So use the followings after they become stable
1957 //ewk_context_cache_clear(This->m_ewkContext);
1958 //ewk_context_notify_low_memory(This->m_ewkContext);
1964 void ViewLogic::databaseUsagePermissionRequestCallback(
1966 Evas_Object* /*obj*/,
1969 LogDebug("databaseUsagePermissionRequestCallback called");
1971 ViewLogic* This = static_cast<ViewLogic*>(data);
1974 ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
1976 This->m_securityOriginSupport->getSecurityOriginDAO(),
1981 void ViewLogic::fileSystemPermissionRequestCallback(
1983 Evas_Object* /*obj*/,
1986 LogDebug("fileSystemPermissionRequestCallback called");
1988 ViewLogic* This = static_cast<ViewLogic*>(data);
1990 ViewModule::FileSystemSupport::fileSystemPermissionRequest(
1992 This->m_securityOriginSupport->getSecurityOriginDAO(),
1996 void ViewLogic::didRecieveMessageFromInjectedBundle(
1998 const char* /*body*/)
2000 LogDebug("did recive message " << name);
2003 void ViewLogic::didReceiveSynchronousMessage(
2008 LogDebug("didReceiveSynchronousMessage called");
2013 LogDebug("body is empty");
2017 if (!strcmp(name, uriBlockedMessageName)) {
2018 LogDebug("received : " << uriBlockedMessageName);
2019 // Currently WebProcess informs obly about blocked
2020 // URI - URI localization and security chekcs are
2021 // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2022 // and bundle_uri_handling.cpp)
2023 rememberBlockedURI(DPL::FromUTF8String(body));
2025 } else if (!strcmp(name, uriChangedMessageName)) {
2026 LogDebug("received : " << uriChangedMessageName);
2027 std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2028 *returnData = strdup(ret.c_str());
2032 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2034 m_blockedUri = DPL::ToUTF8String(inputURI);
2035 LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2039 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2041 using namespace ViewModule::SecuritySupport;
2043 std::string url = DPL::ToUTF8String(changedURL);
2044 LogInfo("URL = [" << url << "]");
2047 // If url is same to URICHANGE_BLOCKED_URL,
2048 // this url has been already blocked by willsend.
2049 // So current page should be moved to previous page
2050 if (url == URICHANGE_BLOCKED_URL)
2052 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2054 // block this page and open it in browser
2055 LogDebug("Request was blocked by WARP: " << url.c_str());
2056 if (!m_blockedUri.empty()) {
2057 LogDebug("open browser : " << m_blockedUri);
2058 bundle* bundleData = bundle_create();
2059 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2060 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2061 CONTROLLER_POST_EVENT(
2062 ApplicationLauncher,
2063 ApplicationLauncherEvents::LaunchApplicationByAppService(
2067 m_blockedUri = std::string();
2070 if (ewk_view_back_possible(m_currentEwkView)) {
2071 // go back to previous page
2072 ewk_view_back(m_currentEwkView);
2074 // stop current page
2075 ewk_view_stop(m_currentEwkView);
2076 ecore_idler_add(windowCloseIdlerCallback, this);
2079 // This is used in case of returning previous page
2081 return URICHANGE_PLUGIN_NO_CHANGE;
2086 // Check if this url with 'http' or 'https' is included in whitelist,
2087 // which has lists of accessible external documents and
2088 // used for ONLY Tizen app
2089 std::string matchedScheme;
2090 std::string matchedUri;
2091 pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2094 ViewModule::Scheme scheme(matchedScheme);
2095 if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2096 scheme.GetType() == ViewModule::Scheme::HTTPS)
2098 if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2099 if (!checkWhitelist(url.c_str())) {
2100 LogInfo("This uri is not included in white document list");
2101 return URICHANGE_PLUGIN_STOP_ONLY;
2103 LogInfo("This url is included in WhiteList");
2105 // For WAC app, WRT should block access of device api
2106 // for external documents
2107 return URICHANGE_PLUGIN_STOP_ONLY;
2111 // register javascript object for plugins to be used
2112 LogInfo("Register Plugin Objects");
2113 return URICHANGE_PLUGIN_RESTART;
2116 void ViewLogic::windowClose()
2118 LogDebug("windowClose");
2119 Assert(m_closedEwkView && "no closed webview");
2121 if (1 >= m_ewkViewList.size()) {
2122 if (!m_cbs->webkitExit.empty()) {
2123 m_cbs->webkitExit();
2126 // call user callbacks
2127 if (!m_cbs->bufferUnset.empty()) {
2128 m_cbs->bufferUnset(m_currentEwkView);
2130 if (!m_cbs->windowClose.empty()) {
2131 m_cbs->windowClose(m_closedEwkView);
2133 removeEwkView(m_closedEwkView);
2135 // get latest ewkView
2136 m_currentEwkView = m_ewkViewList.back();
2137 const char* uri = ewk_view_url_get(m_currentEwkView);
2138 if (NULL == uri || 0 == strlen(uri)) {
2139 m_currentUri.clear();
2145 /* In case we support many pages in parallel
2146 then view is not suspended*/
2147 //resumeEwkView(m_currentEwkView);
2150 if (!m_cbs->bufferSet.empty()) {
2151 m_cbs->bufferSet(m_currentEwkView);