Add resume bundle callback function before reload start page
[platform/framework/web/wrt.git] / src / view / webkit / view_logic.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /**
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
22  */
23 #include "view_logic.h"
24
25 #include <cstring>
26 #include <string>
27 #include <dpl/assert.h>
28 #include <dpl/log/log.h>
29 #include <dpl/optional.h>
30 #include <dpl/string.h>
31
32 #include <appcore-common.h>
33 #include <pcrecpp.h>
34 #include <vconf.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>
38
39 #include <common/application_data.h>
40 #include <common/application_launcher.h>
41 #include <common/scheme.h>
42
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>
59
60 #include <EWebKit2.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>
68
69 #include <appsvc/appsvc.h>
70
71 namespace {
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;
81 // IME State value
82 const char * const IME_STATE_ON = "on";
83 const char * const IME_STATE_OFF = "off";
84
85 // WKPageLoaderClient
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";
92 // WKPageUIClient
93 const char * const EWK_CREATE_WINDOW = "create,window";
94 const char * const EWK_CLOSE_WINDOW = "close,window";
95 // WKPagePolicyClient
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";
101 // WKPageFormClient
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";
114
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";
119
120 // IME Callback
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";
124
125 // Custom handlers
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";
132
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";
139 }
140
141 ViewLogic::ViewLogic():
142     m_ewkContext(0),
143     m_currentEwkView(0),
144     m_window(NULL),
145     m_model(0),
146     m_cbs(new WRT::UserDelegates),
147     m_isBackgroundReload(false),
148     m_appsSupport(new ViewModule::AppsSupport()),
149     m_vibrationSupport(NULL),
150     m_attachedToCustomHandlerDao(false)
151 {
152 }
153
154 ViewLogic::~ViewLogic ()
155 {
156     detachFromCustomHandlersDao();
157 }
158
159 void ViewLogic::createWebView(Ewk_Context* context,
160                               Evas_Object* window)
161 {
162     LogDebug("");
163     initializeEwkContext(context);
164     Assert(NULL != m_ewkContext);
165     Assert(window);
166     m_window = window;
167     createEwkView(evas_object_evas_get(m_window));
168 }
169
170 void ViewLogic::destroyWebView()
171 {
172     if (m_ewkContext) {
173         finalizeEwkContext();
174     }
175 }
176
177 void ViewLogic::initialize()
178 {
179     LogDebug("Initializing");
180     ApplicationLauncherSingleton::Instance().Touch();
181     appcore_set_event_callback(
182         APPCORE_EVENT_LOW_MEMORY,
183         &appcoreLowMemoryCallback,
184         this);
185 }
186
187 void ViewLogic::terminate()
188 {
189     LogDebug("terminating view logic");
190     if (m_model) {
191         hideWidget();
192     } else {
193         LogError("Widget model not created");
194     }
195     LogDebug("done");
196 }
197
198 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
199 {
200     LogDebug("View prepare");
201
202     Assert(m);
203     m_model = m;
204     m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
205     Assert(NULL != m_ewkContext);
206     Assert(m_window);
207
208     ADD_PROFILING_POINT("initializeSupport", "start");
209     initializeSupport();
210     ADD_PROFILING_POINT("initializeSupport", "stop");
211     setStartPage();
212     ewkClientInit(m_currentEwkView);
213     ADD_PROFILING_POINT("prepareEwkView", "start");
214     prepareEwkView(m_currentEwkView);
215     ADD_PROFILING_POINT("prepareEwkView", "stop");
216     initializePluginLoading();
217 }
218
219 void ViewLogic::showWidget()
220 {
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");
225         return;
226     }
227
228     LogInfo("m_currentUri: " << m_currentUri);
229
230     // load page
231     ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
232
233     if (!m_cbs->bufferSet.empty()) {
234         m_cbs->bufferSet(m_currentEwkView);
235     }
236 }
237
238 void ViewLogic::hideWidget()
239 {
240     LogDebug("hiding widget");
241     ViewModule::StorageSupport::deinitializeStorage(m_model);
242     m_appsSupport->deinitialize();
243
244     // temp
245     // m_vibrationSupport->deinitialize();
246
247     while (m_ewkViewList.size()) {
248         LogInfo("pop webview: " << m_ewkViewList.back());
249         removeEwkView(m_ewkViewList.back());
250     }
251     m_ewkViewList.clear();
252 }
253
254 void ViewLogic::suspendWidget()
255 {
256     LogInfo("Pausing widget");
257     Assert(m_model);
258
259     LogDebug("Request bundle to suspend");
260     PluginModuleSupport::suspend(m_ewkContext);
261
262     if (!m_currentEwkView) {
263         LogWarning("Cannot suspend widget without view");
264     } else {
265         suspendWebkit(m_currentEwkView);
266     }
267
268     evas_object_focus_set(m_currentEwkView, EINA_FALSE);
269
270     // call user callback
271     if (!m_cbs->suspend.empty()) {
272         m_cbs->suspend(true);
273     }
274 };
275
276 void ViewLogic::resumeWidget()
277 {
278     LogInfo("Resume widget");
279     Assert(m_model);
280
281     LogDebug("Request bundle to resume");
282     PluginModuleSupport::resume(m_ewkContext);
283
284     if (m_currentEwkView) {
285         resumeWebkit(m_currentEwkView);
286     }
287
288    /* window system team recomend removing this win_raise code. */
289     /*
290     if (m_window) {
291         elm_win_raise(m_window);
292     }
293     */
294     evas_object_focus_set(m_currentEwkView, EINA_TRUE);
295
296     // call user callback
297     if (!m_cbs->resume.empty()) {
298         m_cbs->resume(true);
299     }
300 };
301
302 void ViewLogic::resetWidget()
303 {
304     LogInfo("Resetting Widget");
305
306     // check if already created webview exists
307     if (!m_ewkViewList.size()) {
308         // create new webview
309         createEwkView(evas_object_evas_get(m_window));
310         setStartPage();
311         ewkClientInit(m_currentEwkView);
312         prepareEwkView(m_currentEwkView);
313     } else {
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()),
319                 m_model);
320
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");
324             return;
325         }
326
327         // webview activated
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(
335                 m_ewkContext,
336                 &scale,
337                 ApplicationDataSingleton::Instance().getEncodedBundle());
338             PluginModuleSupport::dispatchJavaScriptEvent(
339                 m_ewkContext,
340                 WrtPlugins::W3C::ServiceCustomEvent,
341                 NULL);
342         } else {
343             LogInfo("service page is loaded");
344             m_currentUri = DPL::ToUTF8String(*servicedUri);
345             ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
346         }
347         elm_win_raise(m_window);
348         evas_object_focus_set(m_currentEwkView, EINA_TRUE);
349     }
350
351     // call user callback
352     if (!m_cbs->reset.empty()) {
353         m_cbs->reset(true);
354     }
355     if (!m_cbs->bufferSet.empty()) {
356         m_cbs->bufferSet(m_currentEwkView);
357     }
358 }
359
360 void ViewLogic::backward()
361 {
362     if (ewk_view_back_possible(m_currentEwkView)) {
363         ewk_view_back(m_currentEwkView);
364     } else {
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);
369         } else {
370             // Back to previous webview
371             LogInfo("Widget move to previous webview");
372             ecore_idler_add(windowCloseIdlerCallback, this);
373         }
374     }
375 }
376
377 void ViewLogic::reload()
378 {
379     ewk_view_reload(m_currentEwkView);
380 }
381
382 void ViewLogic::forward()
383 {
384     if (ewk_view_forward_possible(m_currentEwkView)) {
385         ewk_view_forward(m_currentEwkView);
386     }
387 }
388
389 void ViewLogic::reloadStartPage()
390 {
391     LogInfo("Reload Start Page");
392     // prevent fail to load plugin bundle side
393     m_isBackgroundReload = true;
394     PluginModuleSupport::resume(m_ewkContext);
395
396     if (m_ewkViewList.size() != 0) {
397         while (m_ewkViewList.size() > 0) {
398             if (!m_cbs->bufferUnset.empty()) {
399                 m_cbs->bufferUnset(m_currentEwkView);
400             }
401             removeEwkView(m_currentEwkView);
402         }
403     }
404
405     // create new webview
406     createEwkView(evas_object_evas_get(m_window));
407     ewkClientInit(m_currentEwkView);
408
409     setStartPage();
410     prepareEwkView(m_currentEwkView);
411     initializePluginLoading();
412
413     // load page
414     ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
415
416     // show ewkView
417     if (!m_cbs->bufferSet.empty()) {
418         m_cbs->bufferSet(m_currentEwkView);
419     }
420     LogInfo("Reloading Start Page is done!");
421 }
422
423 Evas_Object* ViewLogic::getCurrentWebview()
424 {
425     LogInfo("get current webview");
426     return m_currentEwkView;
427 }
428
429 void ViewLogic::fireJavascriptEvent(int event, void* data)
430 {
431     PluginModuleSupport::dispatchJavaScriptEvent(
432         m_ewkContext,
433         static_cast<WrtPlugins::W3C::CustomEventType>(event),
434         data);
435 }
436
437 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
438 {
439     m_cbs = cbs;
440 }
441
442 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
443 {
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(
448         newEwkContext,
449         contextMessageFromInjectedBundleCallback,
450         static_cast<void*>(this));
451
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")))
456     {
457         LogInfo("proxy address is empty");
458         ewk_context_proxy_uri_set(newEwkContext, NULL);
459     } else {
460         LogInfo("proxy address [" << proxyAddress << "]");
461         ewk_context_proxy_uri_set(newEwkContext,  proxyAddress);
462     }
463
464     if (proxyAddress) {
465         free(proxyAddress);
466         proxyAddress = NULL;
467     }
468
469     // theme setting
470     const char *theme = elm_theme_get(NULL);
471     if (theme) {
472         m_theme = theme;
473         LogInfo("theme is " << m_theme);
474     }
475
476     // Ewk download callback (WKContextDownloadClient)
477     ewk_context_did_start_download_callback_set(
478         newEwkContext,
479         didStartDownloadCallback,
480         this);
481
482     // set to member value
483     m_ewkContext = newEwkContext;
484 }
485
486 void ViewLogic::finalizeEwkContext()
487 {
488     LogInfo("finalizeEwkContext called");
489     ewk_context_message_from_injected_bundle_callback_set(
490             m_ewkContext,
491             NULL,
492             NULL);
493 //    ewk_context_delete(m_ewkContext);
494 //    m_ewkContext = 0;
495 }
496
497 void ViewLogic::initializeSupport()
498 {
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));
507
508     // temp
509     // m_vibrationSupport->initialize();
510 }
511
512 void ViewLogic::initializePluginLoading()
513 {
514     // inform wrt information for plugin loading to web process
515     PluginModuleSupport::start(
516         m_ewkContext,
517         m_model->TizenId,
518         elm_config_scale_get(),
519         ApplicationDataSingleton::Instance().getEncodedBundle(),
520         m_theme.c_str(),
521         m_model->SettingList.Get().isEncrypted());
522 }
523
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(
528         wkView,
529         EWK_LOAD_STARTED,
530         loadStartedCallback,
531         this);
532     evas_object_smart_callback_add(
533         wkView,
534         EWK_LOAD_FINISHED,
535         loadFinishedCallback,
536         this);
537     evas_object_smart_callback_add(
538         wkView,
539         EWK_TITLE_CHANGED,
540         titleChangedCallback,
541         this);
542     evas_object_smart_callback_add(
543         wkView,
544         EWK_LOAD_PROGRESS,
545         loadProgressCallback,
546         this);
547     evas_object_smart_callback_add(
548         wkView,
549         EWK_LOAD_PROGRESS_FINISHED,
550         loadProgressFinishedCallback,
551         this);
552     evas_object_smart_callback_add(
553         wkView,
554         EWK_PROCESS_CRASHED,
555         processCrashedCallback,
556         this);
557
558     // WKPageUIClient
559     evas_object_smart_callback_add(
560         wkView,
561         EWK_CREATE_WINDOW,
562         createWindowCallback,
563         this);
564     evas_object_smart_callback_add(
565         wkView,
566         EWK_CLOSE_WINDOW,
567         closeWindowCallback,
568         this);
569
570     // WKPagePolicyClient
571     evas_object_smart_callback_add(
572         wkView,
573         EWK_POLICY_NAVIGATION_DECIDE,
574         policyNavigationDecideCallback,
575         this);
576     evas_object_smart_callback_add(
577         wkView,
578         EWK_POLICY_NEWWINDOW_DECIDE,
579         policyNewWindowDecideCallback,
580         this);
581     evas_object_smart_callback_add(
582         wkView,
583         EWK_POLICY_RESPONSE_DECIDE,
584         pageResponseDecideCallback,
585         this);
586
587     // WKPageContextMenuClient
588     evas_object_smart_callback_add(
589         wkView,
590         EWK_CONTEXTMENU_CUSTOMIZE,
591         contextmenuCustomizeCallback,
592         this);
593
594     // WKPageFormClient
595     evas_object_smart_callback_add(
596         wkView,
597         EWK_FORM_SUBMIT,
598         formSubmitCallback,
599         this);
600
601     // EWK Geolocation Callback
602     evas_object_smart_callback_add(
603         wkView,
604         EWK_REQUEST_GEOLOCATION_PERMISSION,
605         geolocationPermissionRequestCallback,
606         this);
607
608     // EWK Notification Callback
609     evas_object_smart_callback_add(
610         wkView,
611         EWK_NOTIFICATION_SHOW,
612         notificationShowCallback,
613         this);
614     evas_object_smart_callback_add(
615         wkView,
616         EWK_NOTIFICATION_CANCEL,
617         notificationCancelCallback,
618         this);
619     evas_object_smart_callback_add(
620         wkView,
621         EWK_NOTIFICATION_PERMISSION_REQUEST,
622         notificationPermissionRequestCallback,
623         this);
624
625     // EWK Vibration Callback
626     evas_object_smart_callback_add(
627         wkView,
628         EWK_VIBRATION_VIBRATE,
629         vibrationVibrateCallback,
630         this);
631     evas_object_smart_callback_add(
632         wkView,
633         EWK_VIBRATION_CANCEL,
634         vibrationCancelCallback,
635         this);
636     evas_object_smart_callback_add(
637         wkView,
638         EWK_CONTEXT_EXCEEDED_QUOATA,
639         databaseUsagePermissionRequestCallback,
640         this);
641     evas_object_smart_callback_add(
642         wkView,
643         EWK_FILESYSTEM_PERMISSION_REQUEST,
644         fileSystemPermissionRequestCallback,
645         this);
646
647     // EWK Orientation Callback
648     //ewk_view_orientation_lock_callback_set(
649     //    wkView,
650     //     orientationLockCallback,
651     //     this);
652
653     // Fullscreen API callbacks
654     evas_object_smart_callback_add(
655         wkView,
656         EWK_FULLSCREEN_ENTER,
657         enterFullscreenCallback,
658         this);
659     evas_object_smart_callback_add(
660         wkView,
661         EWK_FULLSCREEN_EXIT,
662         exitFullscreenCallback,
663         this);
664
665
666     // when ime start to be showed on the webview,
667     // this callback will be called
668     evas_object_smart_callback_add(
669         wkView,
670         EWK_INPUTMETHOD_CHANGED,
671         imeChangedCallback,
672         this);
673
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.
679     //
680     evas_object_smart_callback_add(
681         wkView,
682         EWK_EDITORCLIENT_IME_OPENED,
683         imeOpenedCallback,
684         this);
685
686     // when ime finished to be hidden,
687     // this callback will be called
688     evas_object_smart_callback_add(
689         wkView,
690         EWK_EDITORCLIENT_IME_CLOSED,
691         imeClosedCallback,
692         this);
693
694     // custom content/scheme handlers
695     evas_object_smart_callback_add(
696         wkView,
697         EWK_PROTOCOLHANDLER_REGISTRATION,
698         protocolHandlerRegistrationCallback,
699         this);
700     evas_object_smart_callback_add(
701         wkView,
702         EWK_PROTOCOLHANDLER_ISREGISTERED,
703         protocolHandlerIsRegisteredCallback,
704         this);
705     evas_object_smart_callback_add(
706         wkView,
707         EWK_PROTOCOLHANDLER_UNREGISTRATION,
708         protocolHandlerUnregistrationCallback,
709         this);
710
711     evas_object_smart_callback_add(
712         wkView,
713         EWK_CONTENTHANDLER_REGISTRATION,
714         contentHandlerRegistrationCallback,
715         this);
716     evas_object_smart_callback_add(
717         wkView,
718         EWK_CONTENTHANDLER_ISREGISTERED,
719         contentHandlerIsRegisteredCallback,
720         this);
721     evas_object_smart_callback_add(
722         wkView,
723         EWK_CONTENTHANDLER_UNREGISTRATION,
724         contentHandlerUnregistrationCallback,
725         this);
726 }
727
728 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
729     LogDebug("ewkClientDeinit");
730     Assert(NULL != wkView && "ewk_view not created at this point");
731
732     // WKPageLoaderClient
733     evas_object_smart_callback_del(
734         wkView,
735         EWK_LOAD_STARTED,
736         loadStartedCallback);
737     evas_object_smart_callback_del(
738         wkView,
739         EWK_LOAD_FINISHED,
740         loadFinishedCallback);
741     evas_object_smart_callback_del(
742         wkView,
743         EWK_TITLE_CHANGED,
744         titleChangedCallback);
745     evas_object_smart_callback_del(
746         wkView,
747         EWK_LOAD_PROGRESS,
748         loadProgressCallback);
749     evas_object_smart_callback_del(
750         wkView,
751         EWK_LOAD_PROGRESS_FINISHED,
752         loadProgressFinishedCallback);
753     evas_object_smart_callback_del(
754         wkView,
755         EWK_PROCESS_CRASHED,
756         loadProgressCallback);
757
758     // WKPageUIClient
759     evas_object_smart_callback_del(
760         wkView,
761         EWK_CREATE_WINDOW,
762         createWindowCallback);
763     evas_object_smart_callback_del(
764         wkView,
765         EWK_CLOSE_WINDOW,
766         closeWindowCallback);
767
768     // WKPagePolicyClient
769     evas_object_smart_callback_del(
770         wkView,
771         EWK_POLICY_NAVIGATION_DECIDE,
772         policyNavigationDecideCallback);
773     evas_object_smart_callback_del(
774         wkView,
775         EWK_POLICY_NEWWINDOW_DECIDE,
776         policyNewWindowDecideCallback);
777     evas_object_smart_callback_del(
778         wkView,
779         EWK_POLICY_RESPONSE_DECIDE,
780         pageResponseDecideCallback);
781
782     // WKPageContextMenuClient
783     evas_object_smart_callback_del(
784         wkView,
785         EWK_CONTEXTMENU_CUSTOMIZE,
786         contextmenuCustomizeCallback);
787
788     // WKPageFormClient
789     evas_object_smart_callback_del(
790         wkView,
791         EWK_FORM_SUBMIT,
792         formSubmitCallback);
793
794     // EWK Geolocation Callback
795     evas_object_smart_callback_del(
796         wkView,
797         EWK_REQUEST_GEOLOCATION_PERMISSION,
798         geolocationPermissionRequestCallback);
799
800     // EWK Notification Callback
801     evas_object_smart_callback_del(
802         wkView,
803         EWK_NOTIFICATION_SHOW,
804         notificationShowCallback);
805     evas_object_smart_callback_del(
806         wkView,
807         EWK_NOTIFICATION_CANCEL,
808         notificationCancelCallback);
809     evas_object_smart_callback_del(
810         wkView,
811         EWK_NOTIFICATION_PERMISSION_REQUEST,
812         notificationPermissionRequestCallback);
813
814     // EWK Vibration Callback
815     evas_object_smart_callback_del(
816         wkView,
817         EWK_VIBRATION_VIBRATE,
818         vibrationVibrateCallback);
819     evas_object_smart_callback_del(
820         wkView,
821         EWK_VIBRATION_CANCEL,
822         vibrationCancelCallback);
823
824     evas_object_smart_callback_del(
825         wkView,
826         EWK_CONTEXT_EXCEEDED_QUOATA,
827         databaseUsagePermissionRequestCallback);
828     evas_object_smart_callback_del(
829         wkView,
830         EWK_FILESYSTEM_PERMISSION_REQUEST,
831         fileSystemPermissionRequestCallback);
832
833     // EWK Orientation Callback
834     //ewk_view_orientation_lock_callback_set(
835     //    wkView,
836     //    NULL,
837     //    NULL);
838
839     // ime change/show/hide callback
840     evas_object_smart_callback_del(
841         wkView,
842         EWK_INPUTMETHOD_CHANGED,
843         imeChangedCallback);
844     evas_object_smart_callback_del(
845         wkView,
846         EWK_EDITORCLIENT_IME_OPENED,
847         imeOpenedCallback);
848     evas_object_smart_callback_del(
849         wkView,
850         EWK_EDITORCLIENT_IME_CLOSED,
851         imeClosedCallback);
852
853     // custom content/scheme handlers
854     evas_object_smart_callback_del(
855         wkView,
856         EWK_PROTOCOLHANDLER_REGISTRATION,
857         protocolHandlerRegistrationCallback);
858     evas_object_smart_callback_del(
859         wkView,
860         EWK_PROTOCOLHANDLER_ISREGISTERED,
861         protocolHandlerIsRegisteredCallback);
862     evas_object_smart_callback_del(
863         wkView,
864         EWK_PROTOCOLHANDLER_UNREGISTRATION,
865         protocolHandlerUnregistrationCallback);
866
867     evas_object_smart_callback_del(
868         wkView,
869         EWK_CONTENTHANDLER_REGISTRATION,
870         contentHandlerRegistrationCallback);
871     evas_object_smart_callback_del(
872         wkView,
873         EWK_CONTENTHANDLER_ISREGISTERED,
874         contentHandlerIsRegisteredCallback);
875     evas_object_smart_callback_del(
876         wkView,
877         EWK_CONTENTHANDLER_UNREGISTRATION,
878         contentHandlerUnregistrationCallback);
879 }
880
881 void ViewLogic::createEwkView(Evas* canvas)
882 {
883     LogDebug("createEwkVeiw");
884     Assert(canvas);
885     ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
886     Evas_Object* newEwkView = ewk_view_add_with_context(
887         canvas,
888         m_ewkContext);
889     ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
890
891     if (!newEwkView) {
892         LogError("WKView creation failed");
893         Assert(false);
894     }
895
896     // set cookie policy
897     // even arguments pass the ewkContext, this API should be called
898     // after webkit Evas_Object is created
899     Ewk_Cookie_Manager *ewkCookieManager;
900     ewkCookieManager =
901         ewk_context_cookie_manager_get(m_ewkContext);
902     ewk_cookie_manager_accept_policy_set(ewkCookieManager,
903                            EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
904
905     LogInfo("push webview: " << newEwkView);
906     m_ewkViewList.push_back(newEwkView);
907     m_currentEwkView = newEwkView;
908 }
909
910 void ViewLogic::setStartPage()
911 {
912     /* Start URI (as other uris) is now localized
913      * on WebProcess side */
914     m_currentUri = m_startUrl;
915 }
916
917 void ViewLogic::prepareEwkView(Evas_Object *wkView)
918 {
919     LogDebug("prepareEwkView called");
920     Assert(wkView);
921     Ewk_Settings* settings = ewk_view_settings_get(wkView);
922
923     // set user agent
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());
929     }
930
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());
940     }
941
942     // webkit NPAPI plugins is always on in wrt
943     ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
944
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);
955
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);
961
962     // set cookie database path
963     // The followings are not implemeted yet by webkit2
964     //      ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
965
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,
971                                        EINA_TRUE);
972 }
973
974 void ViewLogic::removeEwkView(Evas_Object *wkView)
975 {
976     LogInfo("removeEwkView called");
977     Assert(wkView);
978     Assert(0 != m_ewkViewList.size());
979
980     // unregister webview callbacks
981     ewkClientDeinit(wkView);
982
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);
987 }
988
989 void ViewLogic::resumeEwkView(Evas_Object *wkView)
990 {
991     LogInfo("resumeEwkView called");
992     Assert(wkView);
993
994     // register webview callback
995     ewkClientInit(wkView);
996
997     // resume webkit
998     resumeWebkit(wkView);
999
1000     return;
1001 }
1002
1003 void ViewLogic::suspendEwkView(Evas_Object *wkView)
1004 {
1005     LogInfo("suspendEwkView called");
1006     Assert(wkView);
1007
1008     // suspend webkit
1009     suspendWebkit(wkView);
1010
1011     // unregister webview callbacks
1012     ewkClientDeinit(wkView);
1013
1014     return;
1015 }
1016
1017 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1018 {
1019     LogDebug("resumeWebkit");
1020     Assert(wkView);
1021
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,
1033                                        EINA_FALSE);
1034     return;
1035 }
1036
1037 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1038 {
1039     LogDebug("suspendWebkit");
1040     Assert(wkView);
1041
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);
1046
1047     // send visibility event to webpage
1048     ewk_view_page_visibility_state_set(wkView,
1049                                        EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1050                                        EINA_FALSE);
1051     ewk_view_suspend(wkView);
1052     ewk_view_visibility_set(wkView, EINA_FALSE);
1053     return;
1054 }
1055
1056 void ViewLogic::contextMessageFromInjectedBundleCallback(
1057         const char* name,
1058         const char* body,
1059         char** returnData,
1060         void* clientInfo)
1061 {
1062     LogDebug("contextMessageFromInjectedBundleCallback called");
1063     Assert(clientInfo);
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
1072     // };
1073     if (NULL == returnData) {
1074         This->didRecieveMessageFromInjectedBundle(name, body);
1075     } else {
1076         This->didReceiveSynchronousMessage(name, body, returnData);
1077     }
1078 }
1079
1080 void ViewLogic::didStartDownloadCallback(
1081         const char* downloadUrl,
1082         void* data)
1083 {
1084     LogDebug("didStartDownloadCallback called");
1085     Assert(data);
1086     ViewLogic* This = static_cast<ViewLogic*>(data);
1087     Assert(downloadUrl);
1088     LogDebug("download url = " << downloadUrl);
1089     This->m_appsSupport->downloadRequest(
1090         downloadUrl,
1091         NULL,
1092         NULL);
1093 }
1094
1095 void ViewLogic::loadStartedCallback(
1096         void* data,
1097         Evas_Object* obj,
1098         void* /*eventInfo*/)
1099 {
1100     LogDebug("loadStartedCallback called");
1101     Assert(data);
1102     ViewLogic* This = static_cast<ViewLogic*>(data);
1103     evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1104
1105     // call loadFinish callback to wrt-client
1106     if (!This->m_cbs->loadStart.empty()) {
1107         This->m_cbs->loadStart(obj);
1108     }
1109
1110 }
1111
1112 void ViewLogic::loadFinishedCallback(
1113         void* data,
1114         Evas_Object* obj,
1115         void* /*eventInfo*/)
1116 {
1117     LogDebug("loadFinishedCallback called");
1118     Assert(data);
1119     ViewLogic* This = static_cast<ViewLogic*>(data);
1120
1121     // Fill id/password
1122     const char* url = ewk_view_url_get(This->m_currentEwkView);
1123     if (NULL == url || strlen(url) == 0) {
1124         LogError("url is empty");
1125     } else {
1126         DPL::OptionalString jsOptionalString =
1127             ViewModule::PasswordSupport::jsForAutoFillData(url);
1128         if (jsOptionalString.IsNull()) {
1129             LogError("Fail to get JS String");
1130         } else {
1131             std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1132
1133             if(EINA_FALSE == ewk_view_script_execute(
1134                 This->m_currentEwkView,
1135                 jsStr.c_str(),
1136                 didRunJavaScriptCallback,
1137                 This))
1138             {
1139                 LogError("JS for auto fill data failed.");
1140             }
1141         }
1142     }
1143
1144     // call loadFinish callback to wrt-client
1145     if (!This->m_cbs->loadFinish.empty()) {
1146         This->m_cbs->loadFinish(obj);
1147     }
1148
1149     // set only encoded bundle
1150     double scale = elm_config_scale_get();
1151     PluginModuleSupport::setCustomProperties(
1152         This->m_ewkContext,
1153         &scale,
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(
1158         This->m_ewkContext,
1159         WrtPlugins::W3C::ServiceCustomEvent,
1160         NULL);
1161
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;
1168     }
1169 }
1170
1171 void ViewLogic::titleChangedCallback(
1172         void* data,
1173         Evas_Object* /*obj*/,
1174         void* eventInfo)
1175 {
1176     LogDebug("titleChangedCallback called");
1177     Assert(data);
1178     ViewLogic* This = static_cast<ViewLogic*>(data);
1179     Assert(eventInfo);
1180     const char* title = static_cast<char*>(eventInfo);
1181
1182     if (0 == strlen(title)) {
1183         LogDebug("title data is empty");
1184         return;
1185     }
1186     LogDebug("Title = [" << title << "]");
1187     This->m_schemeSupport->HandleTizenScheme(title,
1188                                              This->m_window,
1189                                              This->m_currentEwkView);
1190 }
1191
1192 void ViewLogic::loadProgressCallback(
1193         void* /*data*/,
1194         Evas_Object* /*obj*/,
1195         void* eventInfo)
1196 {
1197     double* progress = static_cast<double*>(eventInfo);
1198     LogDebug("didChangeProgressCallback progress = " << *progress);
1199 }
1200
1201 void ViewLogic::loadProgressFinishedCallback(
1202         void* data,
1203         Evas_Object* /*obj*/,
1204         void* /*eventInfo*/)
1205 {
1206     LogDebug("didFinishProgressCallback");
1207     Assert(data);
1208     ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1209     if (!view->m_cbs->progressFinish.empty()) {
1210         view->m_cbs->progressFinish();
1211     }
1212 }
1213
1214 void ViewLogic::processCrashedCallback(
1215         void* data,
1216         Evas_Object* /*obj*/,
1217         void* eventInfo)
1218 {
1219     LogInfo("processCrashedCallback");
1220     Assert(data);
1221     ViewLogic const * const view =
1222             static_cast<ViewLogic const * const>(data);
1223     if (!view->m_cbs->webCrash.empty()) {
1224         view->m_cbs->webCrash();
1225     }
1226     // This flag will be prevented exit() call in the Webkit side
1227     if (NULL != eventInfo) {
1228         *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1229     }
1230 }
1231
1232 void ViewLogic::createWindowCallback(
1233         void* data,
1234         Evas_Object* obj,
1235         void* eventInfo)
1236 {
1237     LogDebug("createWindowCallback");
1238     Assert(data);
1239     ViewLogic* This = static_cast<ViewLogic*>(data);
1240
1241     // First, current webview should be handled by user callback
1242     if (!This->m_cbs->bufferUnset.empty()) {
1243         This->m_cbs->bufferUnset(obj);
1244     }
1245
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);
1251     }
1252     if (!canvas) {
1253         canvas = evas_object_evas_get(This->m_window);
1254     }
1255
1256     // create new ewkview
1257     This->createEwkView(canvas);
1258     Evas_Object* newEwkView = This->m_currentEwkView;
1259
1260     // initialize new ewkview
1261     This->setStartPage();
1262     This->ewkClientInit(newEwkView);
1263     This->prepareEwkView(newEwkView);
1264
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);
1269     }
1270
1271     // Lastly, new webview should be handled by user callback
1272     if (!This->m_cbs->bufferSet.empty()) {
1273         This->m_cbs->bufferSet(newEwkView);
1274     }
1275     *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1276 }
1277
1278 void ViewLogic::closeWindowCallback(
1279         void* data,
1280         Evas_Object* obj,
1281         void* /*eventInfo*/)
1282 {
1283     LogDebug("closeWindowCallback");
1284     ViewLogic* This = static_cast<ViewLogic*>(data);
1285     This->m_closedEwkView = obj;
1286     ecore_idler_add(windowCloseIdlerCallback, This);
1287 }
1288
1289 void ViewLogic::policyNavigationDecideCallback(
1290         void* data,
1291         Evas_Object* /*obj*/,
1292         void* eventInfo)
1293 {
1294     LogDebug("policyNavigationDecideCallback called");
1295     Assert(data);
1296     ViewLogic* This = static_cast<ViewLogic*>(data);
1297     Assert(eventInfo);
1298     Ewk_Policy_Decision* policyDecision =
1299         static_cast<Ewk_Policy_Decision*>(eventInfo);
1300
1301     if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1302                                                  false,
1303                                                  This->m_model,
1304                                                  This->m_window,
1305                                                  This->m_currentEwkView))
1306     {
1307         LogDebug("use");
1308         ewk_policy_decision_use(policyDecision);
1309     } else {
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)) {
1313             /*
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).
1319              *
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.
1323              */
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);
1328             } else {
1329                 // stop current WKPage
1330                 ewk_view_stop(This->m_currentEwkView);
1331                 ecore_idler_add(windowCloseIdlerCallback, This);
1332             }
1333         }
1334
1335         LogDebug("ignore");
1336         ewk_policy_decision_ignore(policyDecision);
1337     }
1338 }
1339
1340 void ViewLogic::policyNewWindowDecideCallback(
1341         void* data,
1342         Evas_Object* /*obj*/,
1343         void* eventInfo)
1344 {
1345     LogDebug("policyNewWindowDecideCallback called");
1346     Assert(data);
1347     ViewLogic* This = static_cast<ViewLogic*>(data);
1348     Assert(eventInfo);
1349     Ewk_Policy_Decision* policyDecision =
1350         static_cast<Ewk_Policy_Decision*>(eventInfo);
1351
1352     if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1353                                                  true,
1354                                                  This->m_model,
1355                                                  This->m_window,
1356                                                  This->m_currentEwkView))
1357     {
1358         ewk_policy_decision_use(policyDecision);
1359     } else {
1360         // scheme handled
1361         ewk_policy_decision_ignore(policyDecision);
1362     }
1363 }
1364
1365 void ViewLogic::pageResponseDecideCallback(
1366         void* data,
1367         Evas_Object* /*obj*/,
1368         void* eventInfo)
1369 {
1370     LogDebug("pageResponseDecideCallback called");
1371     Assert(data);
1372     ViewLogic* This = static_cast<ViewLogic*>(data);
1373     Assert(eventInfo);
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);
1378
1379     if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1380         LogDebug("use");
1381         ewk_policy_decision_use(policyDecision);
1382     } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1383         LogDebug("download");
1384         ewk_policy_decision_suspend(policyDecision);
1385
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);
1391             return;
1392         }
1393         LogDebug("url = [" << url << "]");
1394
1395         // get content information
1396         const char* content =
1397             ewk_policy_decision_response_mime_get(policyDecision);
1398         LogDebug("content type = [" << content << "]");
1399
1400         // get cookie information
1401         const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1402         LogDebug("cookie = [" << cookie << "]");
1403
1404         LogDebug("Content not supported, will be opened in external app");
1405         This->m_appsSupport->downloadRequest(
1406             url,
1407             content,
1408             cookie);
1409         ewk_policy_decision_ignore(policyDecision);
1410     } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1411         LogDebug("ignore");
1412         ewk_policy_decision_ignore(policyDecision);
1413     } else {
1414         LogDebug("Type isn't handled");
1415         ewk_policy_decision_ignore(policyDecision);
1416     }
1417 }
1418
1419 void ViewLogic::contextmenuCustomizeCallback(
1420         void* data,
1421         Evas_Object* /*obj*/,
1422         void* eventInfo)
1423 {
1424     LogDebug("contextmenuCustomizeCallback called");
1425     Assert(data);
1426     Assert(eventInfo);
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))
1432     {
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);
1436             Assert(item);
1437             ewk_context_menu_item_remove(menu, item);
1438         }
1439     } else {
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);
1443             Assert(item);
1444             Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1445
1446             switch (tag) {
1447                 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1448                     ewk_context_menu_item_remove(menu, item);
1449                     break;
1450
1451                 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1452                     ewk_context_menu_item_remove(menu, item);
1453                     break;
1454
1455                 default:
1456                     idx++;
1457                     break;
1458             }
1459         }
1460     }
1461 }
1462
1463 void ViewLogic::formSubmitCallback(
1464         void* /*data*/,
1465         Evas_Object* /*obj*/,
1466         void* eventInfo)
1467 {
1468     LogDebug("formSubmitCallback called");
1469     Assert(eventInfo);
1470     Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1471
1472     const char* uri = ewk_form_data_url_get(formData);
1473     if (!uri) {
1474         LogError("URL is empty");
1475         return;
1476     }
1477
1478     Eina_Hash* userData = ewk_form_data_values_get(formData);
1479     ViewModule::PasswordSupport::submitClicked(uri, userData);
1480 }
1481
1482 void ViewLogic::geolocationPermissionRequestCallback(
1483         void* data,
1484         Evas_Object* /*obj*/,
1485         void* eventInfo)
1486 {
1487     Assert(data);
1488     ViewLogic* This = static_cast<ViewLogic*>(data);
1489     Assert(eventInfo);
1490     ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1491         This->m_window,
1492         This->m_securityOriginSupport->getSecurityOriginDAO(),
1493         eventInfo);
1494 }
1495
1496 void ViewLogic::notificationShowCallback(
1497         void* data,
1498         Evas_Object* /*obj*/,
1499         void* eventInfo)
1500 {
1501     LogDebug("notificationShowCallback called");
1502     Assert(data);
1503     ViewLogic* This = static_cast<ViewLogic*>(data);
1504
1505     Assert(eventInfo);
1506     Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1507
1508     using namespace ViewModule::WebNotification;
1509
1510     WebNotificationDataPtr notiData(
1511             new WebNotificationData(
1512                 This->m_model,
1513                 ewk_notification_id_get(noti)));
1514
1515     DPL::OptionalString string =
1516         DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1517     if (!string.IsNull()) {
1518         notiData->m_iconURL = DPL::ToUTF8String(*string);
1519     }
1520     string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1521     if (!string.IsNull()) {
1522         notiData->m_title = DPL::ToUTF8String(*string);
1523     }
1524     string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1525     if (!string.IsNull()) {
1526         notiData->m_body = DPL::ToUTF8String(*string);
1527     }
1528
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);
1533
1534     showWebNotification(notiData);
1535     ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1536 }
1537
1538 void ViewLogic::notificationCancelCallback(
1539         void* /*data*/,
1540         Evas_Object* /*obj*/,
1541         void* /*eventInfo*/)
1542 {
1543     LogDebug("notificationCancelCallback called");
1544 }
1545
1546 void ViewLogic::notificationPermissionRequestCallback(
1547         void* data,
1548         Evas_Object* /*obj*/,
1549         void* eventInfo)
1550 {
1551     LogDebug("notificationPermissionRequestCallback called");
1552     Assert(data);
1553     ViewLogic* This = static_cast<ViewLogic*>(data);
1554
1555     Assert(eventInfo);
1556     Ewk_Notification_Permission_Request* request =
1557         static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1558     ewk_notification_permission_request_response(
1559         This->m_ewkContext,
1560         request,
1561         EINA_TRUE);
1562     return;
1563 }
1564
1565 void ViewLogic::vibrationVibrateCallback(
1566         void* data,
1567         Evas_Object* /*obj*/,
1568         void* eventInfo)
1569 {
1570     LogDebug("vibrationVibrateCallback called");
1571     Assert(data);
1572     ViewLogic* This = static_cast<ViewLogic*>(data);
1573
1574     Assert(eventInfo);
1575     const long vibrationTime = *(static_cast<const long*>(eventInfo));
1576
1577     // temp
1578     // This->m_vibrationSupport->startVibration(vibrationTime);
1579
1580     return;
1581 }
1582
1583 void ViewLogic::vibrationCancelCallback(
1584         void* data,
1585         Evas_Object* /*obj*/,
1586         void* /*eventInfo*/)
1587 {
1588     LogDebug("vibrationCancelCallback called");
1589     Assert(data);
1590     ViewLogic* This = static_cast<ViewLogic*>(data);
1591
1592     // temp
1593     // This->m_vibrationSupport->stopVibration();
1594
1595     return;
1596 }
1597
1598 // EWK Orientation Callback
1599 Eina_Bool ViewLogic::orientationLockCallback(
1600         Evas_Object* obj,
1601         Eina_Bool /*needLock*/,
1602         int orientation,
1603         void* data)
1604 {
1605     LogDebug("orientationLockCallback called");
1606     Assert(data);
1607     ViewLogic* This = static_cast<ViewLogic*>(data);
1608
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);
1625     } else {
1626         LogDebug("Wrong orientation is set");
1627         return EINA_FALSE;
1628     }
1629     return EINA_TRUE;
1630 }
1631
1632
1633 // Fullscreen API callbacks
1634 void ViewLogic::enterFullscreenCallback(
1635         void* data,
1636         Evas_Object* /*obj*/,
1637         void* /*eventInfo*/)
1638 {
1639     LogInfo("enterFullscreenCallback called");
1640     Assert(data);
1641     ViewLogic* This = static_cast<ViewLogic*>(data);
1642     if (!This->m_cbs->toggleFullscreen.empty()) {
1643         This->m_cbs->toggleFullscreen(true);
1644     }
1645 }
1646 void ViewLogic::exitFullscreenCallback(
1647         void* data,
1648         Evas_Object* /*obj*/,
1649         void* /*eventInfo*/)
1650 {
1651     LogInfo("exitFullscreenCallback called");
1652     Assert(data);
1653     ViewLogic* This = static_cast<ViewLogic*>(data);
1654     if (!This->m_cbs->toggleFullscreen.empty()) {
1655         This->m_cbs->toggleFullscreen(false);
1656     }
1657 }
1658
1659 void ViewLogic::imeChangedCallback(
1660         void* data,
1661         Evas_Object* /*obj*/,
1662         void* eventInfo)
1663 {
1664     LogDebug("enter");
1665     Assert(data);
1666     Assert(eventInfo);
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;
1671 }
1672
1673 void ViewLogic::imeOpenedCallback(
1674         void* data,
1675         Evas_Object* /*obj*/,
1676         void* /*eventInfo*/)
1677 {
1678     LogDebug("enter");
1679     Assert(data);
1680     ViewLogic* This = static_cast<ViewLogic*>(data);
1681
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),
1689             &args);
1690 }
1691
1692 void ViewLogic::imeClosedCallback(
1693         void* data,
1694         Evas_Object* /*obj*/,
1695         void* /*eventInfo*/)
1696 {
1697     LogDebug("enter");
1698     Assert(data);
1699     ViewLogic* This = static_cast<ViewLogic*>(data);
1700
1701     using namespace WrtPlugins::W3C;
1702     SoftKeyboardChangeArgs args;
1703     args.state = IME_STATE_OFF;
1704
1705     This->fireJavascriptEvent(
1706             static_cast<int>(SoftKeyboardChangeCustomEvent),
1707             &args);
1708 }
1709
1710 // helper method
1711 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1712 {
1713     Assert(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);
1718     if (base_url) {
1719         LogDebug("base url: " << base_url);
1720         customHandler->base_url = DPL::FromASCIIString(string(base_url));
1721     }
1722     const char* url = ewk_custom_handlers_data_url_get(handler);
1723     if (url) {
1724         LogDebug("url: " << url);
1725         customHandler->url = DPL::FromASCIIString(string(url));
1726     }
1727     const char* target = ewk_custom_handlers_data_target_get(handler);
1728     if (target) {
1729         LogDebug("target: " << target);
1730         customHandler->target = DPL::FromASCIIString(string(target));
1731     }
1732     const char* title = ewk_custom_handlers_data_title_get(handler);
1733     if (title) {
1734         LogDebug("title: " << title);
1735         customHandler->title = DPL::FromASCIIString(string(title));
1736     }
1737     return customHandler;
1738 }
1739
1740 void ViewLogic::attachToCustomHandlersDao()
1741 {
1742     if (!m_attachedToCustomHandlerDao) {
1743         CustomHandlerDB::Interface::attachDatabaseRW();
1744     }
1745 }
1746
1747 void ViewLogic::detachFromCustomHandlersDao()
1748 {
1749     if (m_attachedToCustomHandlerDao) {
1750         CustomHandlerDB::Interface::detachDatabase();
1751     }
1752 }
1753
1754 const int protocolWhiteListLenth = 15;
1755 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1756     "irc",
1757     "geo",
1758     "mailto",
1759     "magnet",
1760     "mms",
1761     "news",
1762     "nntp",
1763     "sip",
1764     "sms",
1765     "smsto",
1766     "ssh",
1767     "tel",
1768     "urn",
1769     "webcal",
1770     "xmpp"
1771 };
1772
1773 const int contentBlackListLenth = 14;
1774 char const * const contentBlackList[contentBlackListLenth] = {
1775     "application/x-www-form-urlencoded",
1776     "application/xhtml+xml",
1777     "application/xml",
1778     "image/gif",
1779     "image/jpeg",
1780     "image/png",
1781     "image/svg+xml",
1782     "multipart/x-mixed-replace",
1783     "text/cache-manifest",
1784     "text/css",
1785     "text/html",
1786     "text/ping",
1787     "text/plain",
1788     "text/xml"
1789 };
1790
1791 /**
1792  * Saves user's response from popup to custom handler. Saves Yes/No and remember
1793  * state.
1794  * @param response
1795  * @param customHandler
1796  */
1797 void saveUserResponse(Wrt::Popup::PopupResponse response,
1798         CustomHandlerDB::CustomHandlerPtr customHandler)
1799 {
1800     switch (response) {
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);
1805             break;
1806         case Wrt::Popup::YES_DONT_REMEMBER:
1807             LogDebug("User allowed, don't remember");
1808             customHandler->user_decision = CustomHandlerDB::Agreed;
1809             break;
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);
1814             break;
1815         case Wrt::Popup::NO_DONT_REMEMBER:
1816             LogDebug("User didn't allow, don't remember");
1817             customHandler->user_decision = CustomHandlerDB::Declined;
1818             break;
1819     }
1820 }
1821
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,
1827                                                     Evas_Object* obj,
1828                                                     void* eventInfo)
1829 {
1830     Assert(data);
1831     LogDebug("enter");
1832     CustomHandlerDB::CustomHandlerPtr customHandler =
1833             getCustomHandlerFromData(eventInfo);
1834
1835     std::string scheme = DPL::ToUTF8String(customHandler->target);
1836     if (scheme.empty()) {
1837         LogError("No scheme provided");
1838         //TODO what about securityError?
1839         return;
1840     }
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()))
1845         {
1846             LogDebug("Match found, protocol can be handled");
1847             matched = true;
1848         }
1849     }
1850     if (!matched) {
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
1855             return;
1856         }
1857         int l = 4;
1858         char c = scheme[l];
1859         while (c != '\0')
1860         {
1861             if (c < 'a' || c > 'z') {
1862                 LogWarning("Wrong char inside scheme. "
1863                            << "Only lowercase ASCII letters accepted");
1864                 //throw SecurityException
1865                 return;
1866             }
1867             c = scheme[++l];
1868         }
1869     }
1870
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,
1877                                            customHandler->url,
1878                                            customHandler->base_url);
1879     if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1880         LogDebug("Protocol already registered - nothing to do");
1881     } else {
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)
1891             return;
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,
1897                     NULL,
1898                     DPL::ToUTF8String(customHandler->target).c_str(),
1899                     DPL::ToUTF8String(This->m_model->TizenId).c_str());
1900             if (APPSVC_RET_OK != ret)
1901             {
1902                 LogWarning("Appsvc entry failed: " << ret);
1903             }
1904         }
1905         LogDebug("Protocal saved");
1906     }
1907
1908     This->detachFromCustomHandlersDao();
1909 }
1910
1911 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1912                                                     Evas_Object* obj,
1913                                                     void* eventInfo)
1914 {
1915     LogDebug("enter");
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,
1923                                            customHandler->url,
1924                                            customHandler->base_url);
1925     if (handler) {
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);
1930         else
1931             ewk_custom_handlers_data_result_set(
1932                 static_cast<Ewk_Custom_Handlers_Data*>(data),
1933                 EWK_CUSTOM_HANDLERS_DECLINED);
1934     } else
1935             ewk_custom_handlers_data_result_set(
1936                 static_cast<Ewk_Custom_Handlers_Data*>(data),
1937                 EWK_CUSTOM_HANDLERS_NEW);
1938     This->detachFromCustomHandlersDao();
1939 }
1940
1941 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1942                                                       Evas_Object* obj,
1943                                                       void* eventInfo)
1944 {
1945     LogDebug("enter");
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,
1954                                        customHandler->url,
1955                                        customHandler->base_url);
1956     if (handlerCheck) {
1957         if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
1958             appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
1959
1960         handlersDao.unregisterProtocolHandler(customHandler->target,
1961                                               customHandler->url,
1962                                               customHandler->base_url);
1963     } else
1964         LogDebug("Nothing to unregister");
1965
1966     This->detachFromCustomHandlersDao();
1967 }
1968
1969 void ViewLogic::contentHandlerRegistrationCallback(void* data,
1970                                                    Evas_Object* obj,
1971                                                    void* eventInfo)
1972 {
1973     Assert(data);
1974     LogDebug("enter");
1975     CustomHandlerDB::CustomHandlerPtr customHandler =
1976             getCustomHandlerFromData(eventInfo);
1977
1978     std::string mimeType = DPL::ToUTF8String(customHandler->target);
1979     if (mimeType.empty()) {
1980         LogError("No mimeType provided.");
1981         return;
1982     }
1983     for (int i = 0; i < contentBlackListLenth; ++i)
1984     {
1985         if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
1986         {
1987             LogWarning("mimeType blacklisted");
1988             //throw SecurityException
1989             return;
1990         }
1991     }
1992
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,
1999                                           customHandler->url,
2000                                           customHandler->base_url);
2001     if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
2002         LogDebug("Protocol already registered - nothing to do");
2003     } else {
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)
2013             return;
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(),
2020                     NULL,
2021                     DPL::ToUTF8String(This->m_model->TizenId).c_str());
2022             if (APPSVC_RET_OK != ret)
2023             {
2024                 LogWarning("Appsvc entry failed: " << ret);
2025             }
2026         }
2027         LogDebug("Content saved");
2028     }
2029     This->detachFromCustomHandlersDao();
2030 }
2031
2032 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
2033                                                    Evas_Object* obj,
2034                                                    void* eventInfo)
2035 {
2036     LogDebug("enter");
2037     CustomHandlerDB::CustomHandlerPtr customHandler =
2038         getCustomHandlerFromData(eventInfo);
2039     ViewLogic* This = static_cast<ViewLogic*>(data);
2040     LogDebug("Creating handlers dao");
2041
2042     This->attachToCustomHandlersDao();
2043     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2044         CustomHandlerDB::CustomHandlerPtr handler =
2045             handlersDao.getContentHandler(customHandler->target,
2046                                           customHandler->url,
2047                                           customHandler->base_url);
2048     if (handler) {
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);
2053         else
2054             ewk_custom_handlers_data_result_set(
2055                 static_cast<Ewk_Custom_Handlers_Data*>(data),
2056                 EWK_CUSTOM_HANDLERS_DECLINED);
2057     } else
2058             ewk_custom_handlers_data_result_set(
2059                 static_cast<Ewk_Custom_Handlers_Data*>(data),
2060                 EWK_CUSTOM_HANDLERS_NEW);
2061     This->detachFromCustomHandlersDao();
2062 }
2063
2064 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
2065                                                      Evas_Object* obj,
2066                                                      void* eventInfo)
2067 {
2068     LogDebug("enter");
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,
2077                                            customHandler->url,
2078                                            customHandler->base_url);
2079         if (handlerCheck) {
2080             if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2081                 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2082
2083             handlersDao.unregisterContentHandler(customHandler->target,
2084                                                      customHandler->url,
2085                                                      customHandler->base_url);
2086         } else
2087             LogDebug("Nothing to unregister");
2088     This->detachFromCustomHandlersDao();
2089 }
2090
2091 void ViewLogic::didRunJavaScriptCallback(
2092         Evas_Object* /*obj*/,
2093         const char* result,
2094         void* /*userData*/)
2095 {
2096     LogInfo("didRunJavaScriptCallback called");
2097     LogInfo("result = " << result);
2098 }
2099
2100 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
2101 {
2102     LogDebug("closeIdlerCallback");
2103     ViewLogic* This = static_cast<ViewLogic*>(data);
2104     This->windowClose();
2105     return ECORE_CALLBACK_CANCEL;
2106 }
2107
2108 int ViewLogic::appcoreLowMemoryCallback(void *data)
2109 {
2110     LogInfo("appcoreLowMemoryCallback");
2111     Assert(data);
2112     ViewLogic* This = static_cast<ViewLogic*>(data);
2113
2114     if (NULL == This->m_ewkContext) {
2115         LogInfo("ewk isn't initialize at this moment");
2116     } else {
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);
2121     }
2122
2123     return 0;
2124 }
2125
2126 void ViewLogic::databaseUsagePermissionRequestCallback(
2127     void* data,
2128     Evas_Object* /*obj*/,
2129     void* eventInfo)
2130 {
2131     LogDebug("databaseUsagePermissionRequestCallback called");
2132     Assert(data);
2133     ViewLogic* This = static_cast<ViewLogic*>(data);
2134
2135     Assert(eventInfo);
2136     ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
2137         This->m_window,
2138         This->m_securityOriginSupport->getSecurityOriginDAO(),
2139         eventInfo);
2140     return;
2141  }
2142
2143 void ViewLogic::fileSystemPermissionRequestCallback(
2144     void* data,
2145     Evas_Object* /*obj*/,
2146     void* eventInfo)
2147 {
2148     LogDebug("fileSystemPermissionRequestCallback called");
2149     Assert(data);
2150     ViewLogic* This = static_cast<ViewLogic*>(data);
2151     Assert(eventInfo);
2152     ViewModule::FileSystemSupport::fileSystemPermissionRequest(
2153         This->m_window,
2154         This->m_securityOriginSupport->getSecurityOriginDAO(),
2155         eventInfo);
2156 }
2157
2158 void ViewLogic::didRecieveMessageFromInjectedBundle(
2159         const char* name,
2160         const char* /*body*/)
2161 {
2162     LogDebug("did recive message " << name);
2163 }
2164
2165 void ViewLogic::didReceiveSynchronousMessage(
2166         const char* name,
2167         const char* body,
2168         char** returnData)
2169 {
2170     LogDebug("didReceiveSynchronousMessage called");
2171     Assert(name);
2172     Assert(returnData);
2173
2174     if (!body) {
2175         LogDebug("body is empty");
2176         *returnData = NULL;
2177         return;
2178     }
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));
2186         *returnData = NULL;
2187     } else if (!strcmp(name, uriChangedMessageName)) {
2188         LogDebug("received : " << uriChangedMessageName);
2189         std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2190         *returnData =  strdup(ret.c_str());
2191     }
2192 }
2193
2194 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2195 {
2196     m_blockedUri = DPL::ToUTF8String(inputURI);
2197     LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2198     return;
2199 }
2200
2201 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2202 {
2203     using namespace ViewModule::SecuritySupport;
2204
2205     std::string url = DPL::ToUTF8String(changedURL);
2206     LogInfo("URL = [" << url << "]");
2207
2208     // check WARP
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)
2213     {
2214         if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2215         {
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(
2226                         bundleData,
2227                         NULL,
2228                         NULL));
2229                 m_blockedUri = std::string();
2230             }
2231         }
2232         if (ewk_view_back_possible(m_currentEwkView)) {
2233             // go back to previous page
2234             ewk_view_back(m_currentEwkView);
2235         } else {
2236             // stop current page
2237             ewk_view_stop(m_currentEwkView);
2238             ecore_idler_add(windowCloseIdlerCallback, this);
2239         }
2240
2241         // This is used in case of returning previous page
2242         m_currentUri = url;
2243         return URICHANGE_PLUGIN_NO_CHANGE;
2244     }
2245
2246     m_currentUri = url;
2247
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(),
2254                                                  &matchedUri,
2255                                                  &matchedScheme);
2256     ViewModule::Scheme scheme(matchedScheme);
2257     if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2258         scheme.GetType() == ViewModule::Scheme::HTTPS)
2259     {
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;
2264             }
2265             LogInfo("This url is included in WhiteList");
2266         } else {
2267             // For WAC app, WRT should block access of device api
2268             // for external documents
2269             return URICHANGE_PLUGIN_STOP_ONLY;
2270         }
2271     }
2272
2273     // register javascript object for plugins to be used
2274     LogInfo("Register Plugin Objects");
2275     return URICHANGE_PLUGIN_RESTART;
2276 }
2277
2278 void ViewLogic::windowClose()
2279 {
2280     LogDebug("windowClose");
2281     Assert(m_closedEwkView && "no closed webview");
2282
2283     if (1 >= m_ewkViewList.size()) {
2284         if (!m_cbs->webkitExit.empty()) {
2285             m_cbs->webkitExit();
2286         }
2287     } else {
2288         // call user callbacks
2289         if (!m_cbs->bufferUnset.empty()) {
2290             m_cbs->bufferUnset(m_currentEwkView);
2291         }
2292         if (!m_cbs->windowClose.empty()) {
2293             m_cbs->windowClose(m_closedEwkView);
2294         }
2295         removeEwkView(m_closedEwkView);
2296
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();
2302         } else {
2303             m_currentUri = uri;
2304         }
2305
2306         // resume ewkView
2307         /* In case we support many pages in parallel
2308            then view is not suspended*/
2309         //resumeEwkView(m_currentEwkView);
2310
2311         // show ewkView
2312         if (!m_cbs->bufferSet.empty()) {
2313             m_cbs->bufferSet(m_currentEwkView);
2314         }
2315     }
2316 }
2317