9e2dc9d9e3e43a9271c1e7ce40aa628af50e4f34
[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 <widget_model.h>
35 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
36
37 #include <common/application_data.h>
38 #include <common/application_launcher.h>
39 #include <common/scheme.h>
40 #include <common/roaming_agent.h>
41
42 #include <common/view_logic_apps_support.h>
43 #include <common/view_logic_custom_header_support.h>
44 #include <common/view_logic_password_support.h>
45 #include <common/view_logic_security_support.h>
46 #include <common/view_logic_storage_support.h>
47 #include <common/view_logic_uri_support.h>
48 #include <common/view_logic_user_agent_support.h>
49 #include <common/view_logic_vibration_support.h>
50 #include <common/view_logic_web_notification_support.h>
51 #include <view_logic_scheme_support.h>
52 #include "view_logic_geolocation_support_webkit2.h"
53 #include "view_logic_utils.h"
54 #include "bundles/plugin_module_support.h"
55
56 #include <ewk_context.h>
57 #include <ewk_context_menu.h>
58 #include <ewk_form_data.h>
59 #include <ewk_network.h>
60 #include <ewk_notification.h>
61 #include <ewk_view.h>
62 #include <ewk_setting.h>
63
64 #include <WebKit2.h>
65 #include <WKPage.h>
66 #include <WKContextMenuItem.h>
67 #include <WKURLResponseEfl.h>
68 #include <WKURLRequestEfl.h>
69 #include <js_overlay_types.h>
70 #include <i_runnable_widget_object.h>
71
72
73 namespace {
74 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
75 const char * const willSendMessageName = "will_send_msg";
76 const char * const uriChangedMessageName = "uri_changed_msg";
77 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
78 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
79 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
80 const char * const URICHANGE_BLOCKED_URL = "null";
81 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
82 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
83
84 // ewk callback
85 const char * const EWK_CREATE_WINDOW = "create,window";
86 const char * const EWK_CLOSE_WINDOW = "close,window";
87 const char * const EWK_CONTEXTMENU_CUSTOMIZE = "contextmenu,customize";
88 const char * const EWK_FORM_SUBMIT = "form,submit";
89 const char * const EWK_REQUEST_GEOLOCATION_PERMISSION =
90     "request,geolocation,permission";
91 const char * const EWK_NOTIFICATION_SHOW = "notification,show";
92 const char * const EWK_NOTIFICATION_CANCEL = "notification,cancel";
93 const char * const EWK_NOTIFICATION_PERMISSION_REQUEST =
94     "notification,permission,request";
95 const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
96 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
97
98 }
99
100 void ViewLogic::createWebView(Ewk_Context* context,
101                               Evas_Object* window)
102 {
103     LogDebug("");
104     initializeEwkContext(context);
105     Assert(NULL != m_ewkContext);
106     Assert(window);
107     m_window = window;
108     createEwkView();
109 }
110
111 void ViewLogic::destroyWebView()
112 {
113     if (m_ewkContext) {
114         finalizeEwkContext();
115     }
116 }
117
118 void ViewLogic::initialize()
119 {
120     LogDebug("Initializing");
121     ApplicationLauncherSingleton::Instance().Touch();
122
123     appcore_set_event_callback(
124         APPCORE_EVENT_LOW_MEMORY,
125         &appcoreLowMemoryCallback,
126         this);
127 }
128
129 void ViewLogic::terminate()
130 {
131     LogDebug("terminating view logic");
132     if (m_model) {
133         hideWidget();
134     } else {
135         LogError("Widget model not created");
136     }
137     LogDebug("done");
138 }
139
140 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
141 {
142     LogDebug("View prepare");
143
144     Assert(m);
145     m_model = m;
146     m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
147
148     Assert(NULL != m_ewkContext);
149     Assert(m_window);
150
151     initializeSupport();
152     setStartPage();
153     ewkClientInit(m_currentEwkView);
154     prepareEwkView(m_currentEwkView);
155     initializePluginLoading();
156 }
157
158 void ViewLogic::initializePluginLoading()
159 {
160     // inform wrt information for plugin loading to web process
161     PluginModuleSupport::start(
162         m_ewkContext,
163         m_model->Handle.Get(),
164         elm_config_scale_get(),
165         ApplicationDataSingleton::Instance().getEncodedBundle(),
166         m_theme.c_str(),
167         m_model->SettingList.Get().isEncrypted());
168 }
169
170 void ViewLogic::initializeSupport()
171 {
172     // set local stroage database path
173     WrtDB::WidgetDAOReadOnly dao(m_model->Handle.Get());
174     ewk_context_web_storage_path_set(m_ewkContext,
175                                      dao.getPrivateLocalStoragePath().c_str());
176     m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
177     ViewModule::StorageSupport::initializeStorage(m_model);
178     m_appsSupport->initialize(m_model);
179     m_vibrationSupport->initialize();
180     ViewModule::GeolocationSupport::Webkit2::initialize(m_model->Handle.Get());
181     ViewModule::GeolocationSupport::Webkit2::
182         adjustGeolocationModuleState(m_currentEwkView);
183 }
184
185 void ViewLogic::showWidget()
186 {
187     LogDebug("showing widget");
188     Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
189     if (m_currentUri.empty()) {
190         LogError("Localized current URI doesn't exist");
191         return;
192     }
193
194     LogInfo("m_currentUri: " << m_currentUri);
195
196     RoamingAgentSingleton::Instance().setDisconnectCallback(
197         DPL::MakeDelegate(this,
198                           &ViewLogic::disconnectNetworkConnectionsFunction));
199
200     // load page
201     WKURLRef baseUrl = WKURLCreateWithUTF8CString(
202         m_currentUri.c_str());
203     if (!baseUrl) {
204         LogError("URL creation failed");
205         return;
206     }
207     WKPageLoadURL(ewk_view_WKPage_get(m_currentEwkView), baseUrl);
208     WKRelease(baseUrl);
209
210     if (m_cbs->bufferSet) {
211         m_cbs->bufferSet(m_currentEwkView, m_cbsData);
212     }
213 }
214
215 void ViewLogic::hideWidget()
216 {
217     LogDebug("hiding widget");
218     RoamingAgentSingleton::Instance().unsetDisconnectCallback();
219     ViewModule::StorageSupport::deinitializeStorage(m_model);
220     m_appsSupport->deinitialize();
221     m_vibrationSupport->deinitialize();
222     // almost terminate time spends for terminate webkit.
223     // after block this evas_object_del code, webkit will be destoryed
224     // with parent evas_object(~WindowData())
225     //FOREACH(it, m_ewkViewList) {
226     //    evas_object_del(*it);
227     //}
228     m_ewkViewList.clear();
229 }
230
231 void ViewLogic::suspendWidget()
232 {
233     LogInfo("Pausing widget");
234     Assert(m_model);
235
236     if (!m_currentEwkView) {
237         LogWarning("Cannot suspend widget without view");
238     } else {
239         suspendWebkit(m_currentEwkView);
240     }
241
242     // call user callback
243     if (m_cbs->suspend) {
244         m_cbs->suspend(true, m_cbsData);
245     }
246 };
247
248 void ViewLogic::resumeWidget()
249 {
250     LogInfo("Resume widget");
251     Assert(m_model);
252
253     if (m_currentEwkView) {
254         resumeWebkit(m_currentEwkView);
255     }
256
257     if (m_window) {
258         elm_win_activate(m_window);
259     }
260     evas_object_focus_set(m_currentEwkView, EINA_TRUE);
261
262     // call user callback
263     if (m_cbs->resume) {
264         m_cbs->resume(true, m_cbsData);
265     }
266 };
267
268 void ViewLogic::resetWidget()
269 {
270     LogInfo("Resetting Widget");
271
272     // check if already created webview exists
273     if (!m_ewkViewList.size()) {
274         // create new webview
275         createEwkView();
276         setStartPage();
277         ewkClientInit(m_currentEwkView);
278         prepareEwkView(m_currentEwkView);
279     } else {
280         bundle *bundle = ApplicationDataSingleton::Instance().getBundle();
281         const char *operation = appsvc_get_operation(bundle);
282         LogInfo("operation : " << operation);
283         if (operation &&
284                 !strcmp(operation, APPSVC_OPERATION_DEFAULT)) {
285             // ignore default operation that is reserved by system
286             // just activate current window
287             LogInfo("raise window");
288             elm_win_raise(m_window);
289             resumeWebkit(m_currentEwkView);
290             return;
291         }
292
293         // check if current url is service url for this tizen service
294         std::string requestedUri =
295                 ViewModule::UriSupport::getUri(m_model, m_startUrl);
296         DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
297                 DPL::FromUTF8String(requestedUri.c_str()),
298                 m_model);
299         if (m_currentUri == DPL::ToUTF8String(*servicedUri)) {
300             // set only encoded bundle
301             double scale = elm_config_scale_get();
302
303             PluginModuleSupport::setCustomProperties(
304                 m_ewkContext,
305                 &scale,
306                 ApplicationDataSingleton::Instance().getEncodedBundle());
307             // dispatch 'appservice' js event
308             PluginModuleSupport::dispatchJavaScriptEvent(
309                 m_ewkContext,
310                 WrtPlugins::W3C::ServiceCustomEvent);
311             // window activate
312             if (m_window) {
313                 elm_win_raise(m_window);
314             }
315             resumeWebkit(m_currentEwkView);
316             return;
317         } else {
318             m_currentUri = DPL::ToUTF8String(*servicedUri);
319         }
320     }
321
322     // inform wrt information for plugin loading to web process
323     PluginModuleSupport::start(
324         m_ewkContext,
325         m_model->Handle.Get(),
326         elm_config_scale_get(),
327         ApplicationDataSingleton::Instance().getEncodedBundle(),
328         m_theme.c_str(),
329         m_model->SettingList.Get().isEncrypted());
330
331     // load page
332     WKURLRef baseUrl = WKURLCreateWithUTF8CString(
333         m_currentUri.c_str());
334     if (!baseUrl) {
335         LogError("URL creation failed");
336         return;
337     }
338     WKPageLoadURL(ewk_view_WKPage_get(m_currentEwkView), baseUrl);
339     WKRelease(baseUrl);
340     resumeWebkit(m_currentEwkView);
341
342     // call user callback
343     if (m_cbs->reset) {
344         m_cbs->reset(true, m_cbsData);
345     }
346     if (m_cbs->bufferSet) {
347         m_cbs->bufferSet(m_currentEwkView, m_cbsData);
348     }
349 }
350
351 void ViewLogic::goBack()
352 {
353     if (WKPageCanGoBack(ewk_view_WKPage_get(m_currentEwkView))) {
354         WKPageGoBack(ewk_view_WKPage_get(m_currentEwkView));
355     } else {
356         if (1 >= m_ewkViewList.size()) {
357             // If there is no previous page, widget move to backgroud.
358             LogInfo("Widget move to backgroud");
359             elm_win_lower(m_window);
360         } else {
361             // Back to previous webview
362             LogInfo("Widget move to previous webview");
363             ecore_idler_add(windowCloseIdlerCallback, this);
364         }
365     }
366 }
367
368 Evas_Object* ViewLogic::getCurrentWebview()
369 {
370     LogInfo("get current webview");
371     return m_currentEwkView;
372 }
373
374 void ViewLogic::setUserCallbacks(WRT::UserCallbacksPtr cbs, void *data)
375 {
376     m_cbs = cbs;
377     m_cbsData = data;
378 }
379
380 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
381 {
382     LogInfo("initializeEwkContext called");
383     Assert(newEwkContext && "Ewk_Context provided can not be null");
384     // bundle callback setting
385     ewk_context_message_from_injected_bundle_callback_set(
386         newEwkContext,
387         contextMessageFromInjectedBundleCallback,
388         static_cast<void*>(this));
389
390     // proxy server setting
391     char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
392     if ((!proxyAddress) || (strlen(proxyAddress) == 0)
393         || (strstr(proxyAddress, "0.0.0.0")))
394     {
395         LogInfo("proxy address is empty");
396         ewk_context_proxy_uri_set(newEwkContext, NULL);
397     } else {
398         LogInfo("proxy address [" << proxyAddress << "]");
399         ewk_context_proxy_uri_set(newEwkContext,  proxyAddress);
400     }
401
402     if (proxyAddress) {
403         free(proxyAddress);
404         proxyAddress = NULL;
405     }
406
407     // theme setting
408     const char *theme = elm_theme_get(NULL);
409     if (theme) {
410         m_theme = theme;
411         LogInfo("theme is " << m_theme);
412     }
413
414     // set download callback
415     //WKContextDownloadClient downloadClient = {
416     //        kWKContextDownloadClientCurrentVersion,
417     //        ewkContext,
418     //        didStartDownload,
419     //        0, // didReceiveAuthenticationChallenge
420     //        0, // didReceiveResponse
421     //        0, // didReceiveData
422     //        0, // shouldDecodeSourceDataOfMIMEType
423     //        0, // decideDestinationWithSuggestedFilename
424     //        0, // didCreateDestination
425     //        0, // didFinish
426     //        0, // didFail
427     //        0, // didCancel
428     //        0 // processDidCrash
429     //    };
430     //    WKContextSetDownloadClient(newEwkContext, &downloadClient);
431     ewk_context_did_start_download_callback_set(
432         newEwkContext,
433         didStartDownloadCallback,
434         this);
435
436     // set to member value
437     m_ewkContext = newEwkContext;
438 }
439
440 void ViewLogic::finalizeEwkContext()
441 {
442     LogInfo("finalizeEwkContext called");
443     ewk_context_delete(m_ewkContext);
444     m_ewkContext = 0;
445 }
446
447
448 ViewLogic::ViewLogic():
449     m_ewkContext(0),
450     m_currentEwkView(0),
451     m_model(0),
452     m_emptyView(false),
453     m_appsSupport(new ViewModule::AppsSupport()),
454     m_vibrationSupport(new ViewModule::VibrationSupport()),
455     m_window(NULL),
456     m_cbs(new WRT::UserCallbacks),
457     m_cbsData(NULL)
458 {
459 }
460
461 ViewLogic::~ViewLogic ()
462 {
463 }
464
465 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
466     Assert(NULL != wkView && "ewk_view not created at this point");
467
468     ViewModule::GeolocationSupport::Webkit2::
469         initialize(m_model->Handle.Get());
470
471     WKPageLoaderClient loaderClient = {
472         kWKPageLoaderClientCurrentVersion, /* version */
473         static_cast<void*>(this), /* clientinfo */
474         didStartProvisionalLoadForFrameCallback, /* didStartProvisionalLoadForFrame */
475         0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
476         0, /* didFailProvisionalLoadWithErrorForFrame */
477         0, /* didCommitLoadForFrame */
478         0, /* didFinishDocumentLoadForFrame */
479         didFinishLoadForFrameCallback, /* didFinishLoadForFrame */
480         0, /* didFailLoadWithErrorForFrame */
481         0, /* didSameDocumentNavigationForFrame */
482         didReceiveTitleForFrameCallback, /* didReceiveTitleForFrame */
483         0, /* didFirstLayoutForFrame */
484         0, /* didFirstVisuallyNonEmptyLayoutForFrame */
485         0, /* didRemoveFrameFromHierarchy */
486         0, /* didDisplayInsecureContentForFrame */
487         0, /* didRunInsecureContentForFrame */
488         0, /* canAuthenticateAgainstProtectionSpaceInFrame */
489         0, /* didReceiveAuthenticationChallengeInFrame */
490         didStartProgressCallback, /* didStartProgressCallback */
491         didChangeProgressCallback, /* didChangeProgress */
492         didFinishProgressCallback, /* didFinishProgress */
493         0, /* processDidBecomeUnresponsive */
494         0, /* processDidBecomeResponsive */
495         processDidCrashCallback, /* processDidCrash */
496         0, /* didChangeBackForwardList */
497         0, /* shouldGoToBackForwardListItem */
498         0, /* didFailToInitializePlugin */
499         0, /* didDetectXSSForFrame */
500         0, /* didNewFirstVisuallyNonEmptyLayout */
501         0, /* willGoToBackForwardListItem */
502         0, /* interactionOccurredWhileProcessUnresponsive */
503         0, /* pluginDidFail */
504     };
505     WKPageSetPageLoaderClient(ewk_view_WKPage_get(wkView), &loaderClient);
506
507     //WKPageUIClient uiClient = {
508     //    kWKPageUIClientCurrentVersion, /* version */
509     //    static_cast<void*>(this), /* clientInfo */
510     //    0,  /* createNewPage_deprecatedForUseWithV0 */
511     //    0, /* showPage*/
512     //    closeCallback, /* close */
513     //    0, /* takeFocus */
514     //    0, /* focus */
515     //    0, /* unfocus */
516     //    0, /* runJavaScriptAlert */
517     //    0, /* runJavaScriptConfirm */
518     //    0, /* runJavaScriptPrompt */
519     //    0, /* setStatusText */
520     //    0, /* mouseDidMoveOverElement */
521     //    0, /* missingPluginButtonClicked */
522     //    0, /* didNotHandleKeyEvent */
523     //    0, /* didNotHandleWheelEvent */
524     //    0, /* toolbarsAreVisible */
525     //    0, /* setToolbarsAreVisible */
526     //    0, /* menuBarIsVisible */
527     //    0, /* setMenuBarIsVisible */
528     //    0, /* statusBarIsVisible */
529     //    0, /* setStatusBarIsVisible */
530     //    0, /* isResizable */
531     //    0, /* setIsResizable */
532     //    0, /* getWindowFrame */
533     //    0, /* setWindowFrame */
534     //    0, /* runBeforeUnloadConfirmPanel */
535     //    0, /* didDraw */
536     //    0, /* pageDidScroll */
537     //    0, /* exceededDatabaseQuota */
538     //    0, /* runOpenPanel */
539     //    decidePolicyForGeolocationPermissionRequestCallback, /* decidePolicyForGeolocationPermissionRequest */
540     //    0, /* headerHeight */
541     //    0, /* footerHeight */
542     //    0, /* drawHeader */
543     //    0, /* drawFooter */
544     //    0, /* printFrame */
545     //    0, /* runModal */
546     //    0, /* didCompleteRubberBandForMainFrame */
547     //    0, /* saveDataToFileInDownloadsFolder */
548     //    0, /* shouldInterruptJavaScript */
549     //    createNewPageCallback,  /* createNewPage */
550     //    0, /* mouseDidMoveOverElement */
551     //    decidePolicyForNotificationPermissionRequestCallback, /* decidePolicyForNotificationPermissionRequest */
552     //};
553     //WKPageSetPageUIClient(ewk_view_page_get(wkView), &uiClient);
554     evas_object_smart_callback_add(
555         wkView,
556         EWK_CREATE_WINDOW,
557         createWindowCallback,
558         this);
559     evas_object_smart_callback_add(
560         wkView,
561         EWK_CLOSE_WINDOW,
562         closeWindowCallback,
563         this);
564
565     WKPagePolicyClient policyClient = {
566         kWKPagePolicyClientCurrentVersion, /* version */
567         static_cast<void*>(this), /* clientInfo */
568         pageDecidePolicyForNavigationActionCallback, /* decidePolicyForNavigationAction */
569         pageDecidePolicyForNewWindowActionCallback, /* decidePolicyForNewWindowAction */
570         pageDecidePolicyForResponseCallback,
571         0,  /* unableToImplementPolicy */
572     };
573     WKPageSetPagePolicyClient(ewk_view_WKPage_get(wkView),
574                               &policyClient);
575
576     // EWK ContextMenu Callback
577     //WKPageContextMenuClient contextMenuClient = {
578     //    kWKPageContextMenuClientCurrentVersion, /* version */
579     //    static_cast<void*>(this), /* clientInfo */
580     //    0, /* getContextMenuFromProposedMenu_deprecatedForUseWithV0 */
581     //    0, /* customContextMenuItemSelected */
582     //    0, /* contextMenuDismissed */
583     //    pageContextMenuForGetMenuCallback /* getContextMenuFromProposedMenu */
584     //};
585     //WKPageSetPageContextMenuClient(ewk_view_page_get(wkView),
586     //                               &contextMenuClient);
587     evas_object_smart_callback_add(
588         wkView,
589         EWK_CONTEXTMENU_CUSTOMIZE,
590         contextmenuCustomizeCallback,
591         this);
592
593     // WKPageFormClient formClient = {
594     //     kWKPageFormClientCurrentVersion, /* version */
595     //     static_cast<void*>(this), /* clientInfo */
596     //     willSubmitFormCallback, /* willSubmitForm */
597     // };
598     // WKPageSetPageFormClient(ewk_view_page_get(wkView), &formClient);
599     evas_object_smart_callback_add(
600         wkView,
601         EWK_FORM_SUBMIT,
602         formSubmitCallback,
603         this);
604
605     // EWK Geolocation Callback
606     //WKGeolocationProvider geolocation_provider = {
607     //    kWKGeolocationProviderCurrentVersion,
608     //    this,
609     //    startUpdatingCallback,
610     //    stopUpdatingCallback
611     //};
612     //WKGeolocationManagerRef geolocation_manager_ref
613     //    = WKContextGetGeolocationManager(m_wkctx);
614     //WKGeolocationManagerSetProvider(geolocation_manager_ref,
615     //        &geolocation_provider);
616     evas_object_smart_callback_add(
617         wkView,
618         EWK_REQUEST_GEOLOCATION_PERMISSION,
619         geolocationPermissionRequestCallback,
620         this);
621     // EWK Notification Callback
622     //WKNotificationProvider notificationProvider = {
623     //    kWKNotificationProviderCurrentVersion, /* version */
624     //    static_cast<void*>(this), /* clientinfo */
625     //    showNotificationCallback, /* show */
626     //    0, /* cancel */
627     //    0, /* didDestroyNotification */
628     //    0, /* addNotificationManager */
629     //    0, /* removeNotificationManager */
630     //    0, /* notificationPermissions */
631     //    0, /* clearNotifications */
632     //};
633     //WKNotificationManagerSetProvider(WKContextGetNotificationManager(m_wkctx),
634     //                                 &notificationProvider);
635     evas_object_smart_callback_add(
636         wkView,
637         EWK_NOTIFICATION_SHOW,
638         notificationShowCallback,
639         this);
640     evas_object_smart_callback_add(
641         wkView,
642         EWK_NOTIFICATION_CANCEL,
643         notificationCancelCallback,
644         this);
645     evas_object_smart_callback_add(
646         wkView,
647         EWK_NOTIFICATION_PERMISSION_REQUEST,
648         notificationPermissionRequestCallback,
649         this);
650     evas_object_smart_callback_add(
651         wkView,
652         EWK_VIBRATION_VIBRATE,
653         vibrationVibrateCallback,
654         this);
655     evas_object_smart_callback_add(
656         wkView,
657         EWK_VIBRATION_CANCEL,
658         vibrationCancelCallback,
659         this);
660
661     // EWK Orientation Callback
662     ewk_view_orientation_lock_callback_set(
663         wkView,
664         orientationLockCallback,
665         this);
666 }
667
668 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
669     LogDebug("ewkClientDeinit");
670     Assert(NULL != wkView && "ewk_view not created at this point");
671
672     // deinit WKPageLoaderClient
673     WKPageLoaderClient loaderClient = {
674         0, /* version */
675         0, /* clientinfo */
676         0, /* didStartProvisionalLoadForFrame */
677         0, /* didReceiveServerRedirectForProvisionalLoadForFrame */
678         0, /* didFailProvisionalLoadWithErrorForFrame */
679         0, /* didCommitLoadForFrame */
680         0, /* didFinishDocumentLoadForFrame */
681         0, /* didFinishLoadForFrame */
682         0, /* didFailLoadWithErrorForFrame */
683         0, /* didSameDocumentNavigationForFrame */
684         0, /* didReceiveTitleForFrame */
685         0, /* didFirstLayoutForFrame */
686         0, /* didFirstVisuallyNonEmptyLayoutForFrame */
687         0, /* didRemoveFrameFromHierarchy */
688         0, /* didDisplayInsecureContentForFrame */
689         0, /* didRunInsecureContentForFrame */
690         0, /* canAuthenticateAgainstProtectionSpaceInFrame */
691         0, /* didReceiveAuthenticationChallengeInFrame */
692         0, /* didStartProgressCallback */
693         0, /* didChangeProgress */
694         0, /* didFinishProgress */
695         0, /* processDidBecomeUnresponsive */
696         0, /* processDidBecomeResponsive */
697         0, /* processDidCrash */
698         0, /* didChangeBackForwardList */
699         0, /* shouldGoToBackForwardListItem */
700         0, /* didFailToInitializePlugin */
701         0, /* didDetectXSSForFrame */
702         0, /* didNewFirstVisuallyNonEmptyLayout */
703         0, /* willGoToBackForwardListItem */
704         0, /* interactionOccurredWhileProcessUnresponsive */
705         0, /* pluginDidFail */
706     };
707     WKPageSetPageLoaderClient(ewk_view_WKPage_get(wkView),
708                               &loaderClient);
709
710     // deinit WKPageUIClient
711     //WKPageUIClient uiClient = {
712     //    0, /* version */
713     //    0, /* clientInfo */
714     //    0,  /* createNewPage_deprecatedForUseWithV0 */
715     //    0, /* showPage*/
716     //    0, /* close */
717     //    0, /* takeFocus */
718     //    0, /* focus */
719     //    0, /* unfocus */
720     //    0, /* runJavaScriptAlert */
721     //    0, /* runJavaScriptConfirm */
722     //    0, /* runJavaScriptPrompt */
723     //    0, /* setStatusText */
724     //    0, /* mouseDidMoveOverElement */
725     //    0, /* missingPluginButtonClicked */
726     //    0, /* didNotHandleKeyEvent */
727     //    0, /* didNotHandleWheelEvent */
728     //    0, /* toolbarsAreVisible */
729     //    0, /* setToolbarsAreVisible */
730     //    0, /* menuBarIsVisible */
731     //    0, /* setMenuBarIsVisible */
732     //    0, /* statusBarIsVisible */
733     //    0, /* setStatusBarIsVisible */
734     //    0, /* isResizable */
735     //    0, /* setIsResizable */
736     //    0, /* getWindowFrame */
737     //    0, /* setWindowFrame */
738     //    0, /* runBeforeUnloadConfirmPanel */
739     //    0, /* didDraw */
740     //    0, /* pageDidScroll */
741     //    0, /* exceededDatabaseQuota */
742     //    0, /* runOpenPanel */
743     //    0, /* decidePolicyForGeolocationPermissionRequest */
744     //    0, /* headerHeight */
745     //    0, /* footerHeight */
746     //    0, /* drawHeader */
747     //    0, /* drawFooter */
748     //    0, /* printFrame */
749     //    0, /* runModal */
750     //    0, /* didCompleteRubberBandForMainFrame */
751     //    0, /* saveDataToFileInDownloadsFolder */
752     //    0, /* shouldInterruptJavaScript */
753     //    0,  /* createNewPage */
754     //    0, /* mouseDidMoveOverElement */
755     //    0, /* decidePolicyForNotificationPermissionRequest */
756     //};
757     //WKPageSetPageUIClient(ewk_view_page_get(wkView), &uiClient);
758     evas_object_smart_callback_del(
759         wkView,
760         EWK_CREATE_WINDOW,
761         createWindowCallback);
762     evas_object_smart_callback_del(
763         wkView,
764         EWK_CLOSE_WINDOW,
765         closeWindowCallback);
766
767
768     // deinit WKPagePolicyClient
769     WKPagePolicyClient policyClient = {
770         0, /* version */
771         0, /* clientInfo */
772         0, /* decidePolicyForNavigationAction */
773         0, /* decidePolicyForNewWindowAction */
774         0, /* decidePolicyForResponse */
775         0,  /* unableToImplementPolicy */
776     };
777     WKPageSetPagePolicyClient(ewk_view_WKPage_get(wkView),
778                               &policyClient);
779
780     // EWK ContextMenu Callback
781     evas_object_smart_callback_del(
782         wkView,
783         EWK_CONTEXTMENU_CUSTOMIZE,
784         contextmenuCustomizeCallback);
785     // deinit WKPageFormClient
786     // WKPageFormClient formClient = {
787     //     0, /* version */
788     //     0, /* clientInfo */
789     //     0, /* willSubmitForm */
790     // };
791     // WKPageSetPageFormClient(ewk_view_page_get(wkView), &formClient);
792     evas_object_smart_callback_del(
793         wkView,
794         EWK_FORM_SUBMIT,
795         formSubmitCallback);
796     // EWK Geolocation Callback
797     evas_object_smart_callback_del(
798         wkView,
799         EWK_REQUEST_GEOLOCATION_PERMISSION,
800         geolocationPermissionRequestCallback);
801     // EWK Notification Callback
802     evas_object_smart_callback_del(
803         wkView,
804         EWK_NOTIFICATION_SHOW,
805         notificationShowCallback);
806     evas_object_smart_callback_del(
807         wkView,
808         EWK_NOTIFICATION_CANCEL,
809         notificationCancelCallback);
810     evas_object_smart_callback_del(
811         wkView,
812         EWK_NOTIFICATION_PERMISSION_REQUEST,
813         notificationPermissionRequestCallback);
814
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     // EWK Orientation Callback
825     ewk_view_orientation_lock_callback_set(
826         wkView,
827         NULL,
828         NULL);
829 }
830
831 void ViewLogic::createEwkView()
832 {
833     LogDebug("createEwkVeiw");
834     Evas_Object* newEwkView = ewk_view_add_with_context(
835         evas_object_evas_get(m_window),
836         m_ewkContext);
837
838     if (!newEwkView) {
839         LogError("WKView creation failed");
840         Assert(false);
841     }
842
843     // set cookie policy
844     // even arguments pass the ewkContext, this API should be called
845     // after webkit Evas_Object is created
846     ewk_context_cookies_policy_set(m_ewkContext, EWK_COOKIE_JAR_ACCEPT_ALWAYS);
847
848     m_ewkViewList.push_back(newEwkView);
849     m_currentEwkView = newEwkView;
850     m_emptyView = true;
851 }
852
853 void ViewLogic::setStartPage()
854 {
855     //TODO: actually this localization should be done in requestWillSend
856     //      callback, but Webkit2 denies access to local files if it detects
857     //      that first loaded file is not 'local' so it wan't work
858     DPL::OptionalString localizedUri = ViewModule::UriSupport::localizeURI(
859             DPL::FromUTF8String(m_startUrl.c_str()),
860             m_model);
861     m_currentUri = DPL::ToUTF8String(*localizedUri);
862 }
863
864 void ViewLogic::prepareEwkView(Evas_Object *wkView)
865 {
866     LogDebug("prepareEwkView called");
867     Assert(wkView);
868     Ewk_Setting* setting = ewk_view_setting_get(wkView);
869
870     // set user agent
871     auto userAgentString =
872         ViewModule::UserAgentSupport::getUserAgentFromVconf();
873     if (!userAgentString.empty()) {
874         LogDebug("Setting custom user agent as: " << userAgentString);
875         ewk_view_user_agent_set(wkView, userAgentString.c_str());
876     }
877
878     // set custom header : language
879     using namespace ViewModule::CustomHeaderSupport;
880     std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
881     if (!customHeaderString.empty()) {
882         LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
883         LogDebug("custom value=[" << customHeaderString << "]");
884         ewk_view_custom_header_add(wkView,
885                                    ACCEPT_LANGUAGE.c_str(),
886                                    customHeaderString.c_str());
887     }
888
889     // enable webkit plugins
890     WrtDB::WidgetDAOReadOnly dao(m_model->Handle.Get());
891     if (dao.getWebkitPluginsRequired()) {
892         ewk_setting_enable_plugins_set(setting, EINA_TRUE);
893     } else {
894         ewk_setting_enable_plugins_set(setting, EINA_FALSE);
895     }
896
897     // The followings are not implemeted yet by webkit2
898     //      ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
899     //      ewk_view_mode_set();
900     //      ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
901     //      ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
902     //      ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
903     //      elm_webview_show_magnifier_set(EINA_FALSE);
904     ewk_setting_enable_scripts_set(setting, EINA_TRUE);
905     ewk_setting_auto_load_images_set(setting, EINA_TRUE);
906     ewk_setting_auto_fitting_set(setting, EINA_FALSE);
907
908     // disable zoom option when user click the input field
909     // this option is useful with the normal website
910     // for the make user friendly, disable auto zoom in the webapp
911     // The followings are not implemeted yet by webkit2
912     //      elm_webview_input_field_zoom_set(EINA_FALSE);
913
914     // set cookie database path
915     // The followings are not implemeted yet by webkit2
916     //      ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
917
918     // set visibility to WebCore. This value will be used for html5.
919     // also, this value will be changed in the suspend, resume
920     // or create window, close window.
921     ewk_view_page_visibility_state_set(wkView,
922                                        EWK_PAGE_VISIBILITY_STATE_VISIBLE,
923                                        EINA_TRUE);
924 }
925
926 void ViewLogic::removeEwkView(Evas_Object *wkView)
927 {
928     LogInfo("removeEwkView called");
929     Assert(wkView);
930     Assert(0 != m_ewkViewList.size());
931
932     // unregister webview callbacks
933     ewkClientDeinit(wkView);
934
935     // suspend NPAPI plugin - Not implemented by Webkit2
936     //    ewk_view_pause_or_resume_plugins();
937     m_ewkViewList.remove(wkView);
938     evas_object_del(wkView);
939 }
940
941 void ViewLogic::resumeEwkView(Evas_Object *wkView)
942 {
943     LogInfo("resumeEwkView called");
944     Assert(wkView);
945
946     // register webview callback
947     ewkClientInit(wkView);
948
949     // resume webkit
950     resumeWebkit(wkView);
951
952     return;
953 }
954
955 void ViewLogic::suspendEwkView(Evas_Object *wkView)
956 {
957     LogInfo("suspendEwkView called");
958     Assert(wkView);
959
960     // suspend webkit
961     suspendWebkit(wkView);
962
963     // unregister webview callbacks
964     ewkClientDeinit(wkView);
965     return;
966 }
967
968 void ViewLogic::resumeWebkit(Evas_Object *wkView)
969 {
970     LogDebug("resumeWebkit");
971     Assert(wkView);
972
973     // resume NPAPI plugin
974     // The followings are not implemeted yet by webkit2
975     //      ewk_view_pause_or_resume_plugins(false);
976     //      ewk_view_pause_or_resume_video_audio(false);
977     //      ewk_view_javascript_resume();
978     //      ewk_view_enable_render();
979     //      ewk_view_reduce_plugins_frame_rate(false);
980     ewk_view_resume(wkView);
981     ewk_view_visibility_set(wkView, EINA_TRUE);
982     ewk_view_page_visibility_state_set(wkView,
983                                        EWK_PAGE_VISIBILITY_STATE_VISIBLE,
984                                        EINA_FALSE);
985     return;
986 }
987
988 void ViewLogic::suspendWebkit(Evas_Object *wkView)
989 {
990     LogDebug("suspendWebkit");
991     Assert(wkView);
992
993     // suspend the followings
994     // The followings are not implemeted yet by webkit2
995     //      ewk_view_pause_or_resume_plugins(true);
996     //      ewk_view_pause_or_resume_video_audio(true);
997
998     // send visibility event to webpage
999     ewk_view_page_visibility_state_set(wkView,
1000                                        EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1001                                        EINA_FALSE);
1002     ewk_view_suspend(wkView);
1003     ewk_view_visibility_set(wkView, EINA_FALSE);
1004     return;
1005 }
1006
1007 void ViewLogic::contextMessageFromInjectedBundleCallback(
1008         const char* name,
1009         const char* body,
1010         char** returnData,
1011         void* clientInfo)
1012 {
1013     LogDebug("contextMessageFromInjectedBundleCallback called");
1014     Assert(clientInfo);
1015     ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1016     // didRecieveMessageFromInjectedBundleCallback - returnData is null
1017     // didReceiveSynchronousMessageCallback - returnData isn't null
1018     // WKContextInjectedBundleClient bundleClient = {
1019     //     kWKContextInjectedBundleClientCurrentVersion,
1020     //     static_cast<void*>(this),
1021     //     &didRecieveMessageFromInjectedBundleCallback,
1022     //     &didReceiveSynchronousMessageCallback
1023     // };
1024     if (NULL == returnData) {
1025         This->didRecieveMessageFromInjectedBundle(name, body);
1026     } else {
1027         This->didReceiveSynchronousMessage(name, body, returnData);
1028     }
1029 }
1030
1031 void ViewLogic::didStartDownloadCallback(
1032         const char* downloadUrl,
1033         void* data)
1034 {
1035     LogDebug("didStartDownloadCallback called");
1036     Assert(data);
1037     ViewLogic* This = static_cast<ViewLogic*>(data);
1038     Assert(downloadUrl);
1039     LogDebug("download url = " << downloadUrl);
1040     This->m_appsSupport->downloadRequest(
1041         downloadUrl,
1042         NULL,
1043         NULL);
1044 }
1045
1046 void ViewLogic::didStartProvisionalLoadForFrameCallback(
1047         WKPageRef /*page*/,
1048         WKFrameRef /*frame*/,
1049         WKTypeRef /*userData*/,
1050         const void *clientInfo)
1051 {
1052     LogDebug("didStartProvisionalLoadForFrameCallback called");
1053     Assert(clientInfo);
1054     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1055     evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1056 }
1057
1058 void ViewLogic::didFinishLoadForFrameCallback(
1059         WKPageRef /*page*/,
1060         WKFrameRef frame,
1061         WKTypeRef /*userData*/,
1062         const void *clientInfo)
1063 {
1064     LogDebug("didFinishLoadForFrameCallback called");
1065     Assert(clientInfo);
1066     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1067
1068     // Fill id/password
1069     DPL::OptionalString urlOptionalString = ViewModule::Utils::toString(frame);
1070     if (urlOptionalString.IsNull()) {
1071         LogError("url is empty");
1072     } else {
1073         std::string urlStr = DPL::ToUTF8String(*urlOptionalString).c_str();
1074         DPL::OptionalString jsOptionalString =
1075             ViewModule::PasswordSupport::jsForAutoFillData(urlStr.c_str());
1076         if (jsOptionalString.IsNull()) {
1077             LogError("Fail to get JS String");
1078         } else {
1079             std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1080             ewk_view_script_execute(
1081                 This->m_currentEwkView,
1082                 jsStr.c_str(),
1083                 didRunJavaScriptCallback,
1084                 This);
1085         }
1086     }
1087
1088     // call loadFinish callback to wrt-client
1089     if (This->m_cbs->loadFinish) {
1090         This->m_cbs->loadFinish(true, This->m_cbsData);
1091     }
1092
1093     // check if 'appsevice' event is registed at the current frames.
1094     // If so, dispatch the event to frames.
1095     PluginModuleSupport::dispatchJavaScriptEvent(
1096         This->m_ewkContext,
1097         WrtPlugins::W3C::ServiceCustomEvent);
1098 }
1099
1100 void ViewLogic::didReceiveTitleForFrameCallback(
1101         WKPageRef page,
1102         WKStringRef title,
1103         WKFrameRef /*frame*/,
1104         WKTypeRef /*userData*/,
1105         const void* clientInfo)
1106 {
1107     LogDebug("didReceiveTitleForFrameCallback called");
1108     Assert(clientInfo);
1109     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1110
1111     DPL::OptionalString titleOptionalString =
1112             ViewModule::Utils::toString(title);
1113     if (titleOptionalString.IsNull()) {
1114         LogDebug("title data is empty");
1115         return;
1116     }
1117
1118     std::string titleStr = DPL::ToUTF8String(*titleOptionalString);
1119     LogDebug("Title = [" << titleStr << "]");
1120
1121     This->m_schemeSupport->HandleTizenScheme(titleStr.c_str(),
1122                                              This->m_window,
1123                                              page);
1124 }
1125
1126 void ViewLogic::didStartProgressCallback(WKPageRef /*page*/,
1127                                                const void* clientinfo)
1128 {
1129     LogDebug("didStartProgressCallback");
1130     Assert(clientinfo);
1131     // TODO : Progress control
1132 }
1133
1134 void ViewLogic::didChangeProgressCallback(WKPageRef page,
1135                                                 const void* /*clientinfo*/)
1136 {
1137     double progress = WKPageGetEstimatedProgress(page);
1138     LogDebug("didChangeProgressCallback progress = " << progress);
1139 }
1140
1141 void ViewLogic::didFinishProgressCallback(WKPageRef /*page*/,
1142                                                 const void* clientinfo)
1143 {
1144     LogDebug("didFinishProgressCallback");
1145     ViewLogic const * const view = static_cast<ViewLogic const * const>(clientinfo);
1146     if (view->m_cbs->progressFinish)
1147         view->m_cbs->progressFinish(view->m_cbsData);
1148 }
1149
1150 void ViewLogic::createWindowCallback(
1151         void* data,
1152         Evas_Object* ,
1153         void* eventInfo)
1154 {
1155     LogDebug("createWindowCallback");
1156     Assert(data);
1157     ViewLogic* This = static_cast<ViewLogic*>(data);
1158
1159     Evas_Object* currentEwkView = This->m_currentEwkView;
1160
1161     // suspend current ewkview
1162     /* In case we support many pages in parallel
1163        then view should not be suspended*/
1164     //This->suspendEwkView(currentEwkView);
1165
1166     if (This->m_cbs->bufferUnset) {
1167         This->m_cbs->bufferUnset(currentEwkView, This->m_cbsData);
1168     }
1169
1170     // create new ewkview
1171     This->createEwkView();
1172
1173     Evas_Object* newEwkView = This->m_currentEwkView;
1174
1175     // initialize new ewkview
1176     This->setStartPage();
1177     This->ewkClientInit(newEwkView);
1178     This->prepareEwkView(newEwkView);
1179
1180     // show new ewkview
1181     if (This->m_cbs->bufferUnset) {
1182         This->m_cbs->bufferSet(newEwkView, This->m_cbsData);
1183     }
1184     *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1185 }
1186
1187 void ViewLogic::closeWindowCallback(
1188         void* data,
1189         Evas_Object* /*obj*/,
1190         void* /*eventInfo*/)
1191 {
1192     LogDebug("closeWindowCallback");
1193     ecore_idler_add(windowCloseIdlerCallback, data);
1194 }
1195
1196 void ViewLogic::pageDecidePolicyForResponseCallback(
1197         WKPageRef /*page*/,
1198         WKFrameRef frame,
1199         WKURLResponseRef response,
1200         WKURLRequestRef request,
1201         WKFramePolicyListenerRef listener,
1202         WKTypeRef /*userData*/,
1203         const void* clientInfo)
1204 {
1205     Assert(clientInfo);
1206     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1207
1208     Assert(response);
1209     WKStringRef contentTypeRef = WKURLResponseEflCopyContentType(response);
1210     Assert(contentTypeRef);
1211     if (WKFrameCanShowMIMEType(frame, contentTypeRef)) {
1212         LogDebug("Accepting this content type to be used by WK2");
1213         WKFramePolicyListenerUse(listener);
1214         WKRelease(contentTypeRef);
1215         return;
1216     }
1217
1218     Assert(request);
1219     // get uri information
1220     DPL::OptionalString requestOptionalStr =
1221             ViewModule::Utils::toString(request);
1222     if (requestOptionalStr.IsNull()) {
1223         LogDebug("uri data is empty");
1224         return;
1225     }
1226     std::string uriStr = DPL::ToUTF8String(*requestOptionalStr).c_str();
1227     const char* uri = uriStr.c_str();
1228     LogDebug("uri = [" << uri << "]");
1229
1230     // get content information
1231     DPL::OptionalString contentOptionalStr =
1232             ViewModule::Utils::toString(contentTypeRef);
1233     std::string contentStr;
1234     if (contentOptionalStr.IsNull()) {
1235         LogDebug("content data is empty");
1236     } else {
1237         contentStr = DPL::ToUTF8String(*contentOptionalStr).c_str();
1238     }
1239     LogDebug("content type = [" << contentStr << "]");
1240
1241     // get cookie information
1242     WKStringRef cookiesRef = WKURLRequestEflCopyCookies(request);
1243     Assert(cookiesRef);
1244     DPL::OptionalString cookiesOptionalStr =
1245             ViewModule::Utils::toString(cookiesRef);
1246     std::string cookieStr;
1247     if (cookiesOptionalStr.IsNull()) {
1248         LogDebug("cookies are empty");
1249     } else {
1250         cookieStr = DPL::ToUTF8String(*cookiesOptionalStr).c_str();
1251     }
1252     LogDebug("cookie = [" << cookieStr << "]");
1253
1254     LogDebug("Content not supported, will be opened in external app");
1255     WKFramePolicyListenerIgnore(listener);
1256     This->m_appsSupport->downloadRequest(
1257         uri,
1258         contentStr.empty() ? NULL : contentStr.c_str(),
1259         cookieStr.empty() ? NULL : cookieStr.c_str());
1260
1261     WKRelease(contentTypeRef);
1262     WKRelease(cookiesRef);
1263 }
1264
1265 void ViewLogic::pageDecidePolicyForNavigationActionCallback(
1266         WKPageRef page,
1267         WKFrameRef frame,
1268         WKFrameNavigationType /*navigationType*/,
1269         WKEventModifiers /*modifiers*/,
1270         WKEventMouseButton /*mouseButton*/,
1271         WKURLRequestRef request,
1272         WKFramePolicyListenerRef listener,
1273         WKTypeRef /*userData*/,
1274         const void* clientInfo)
1275 {
1276     LogDebug("Accepting URL: " << ViewModule::Utils::toString(request));
1277     Assert(clientInfo);
1278
1279     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1280
1281     if (This->m_schemeSupport->filterURIByScheme(page,
1282                                                  frame,
1283                                                  request,
1284                                                  false,
1285                                                  This->m_model,
1286                                                  This->m_window))
1287     {
1288         LogDebug("use");
1289         WKFramePolicyListenerUse(listener);
1290     }
1291     else
1292     {
1293         if(This->m_emptyView)
1294         {
1295             /*
1296              * The view is empty and scheme has been handled externally. When
1297              * user gets back from the external application he'd see blank page
1298              * and won't be able to navigate back. This happens when window.open
1299              * is used to handle schemes like sms/mms/mailto (for example in
1300              * WAC web standards tests: WS-15XX).
1301              *
1302              * To solve the problem, the empty view is removed from the stack
1303              * and the previous one is shown. This is not an elegant solution
1304              * but we don't have a better one.
1305              */
1306             LogInfo("Scheme has been handled externally. Removing empty view.");
1307             if (ewk_view_back_possible(This->m_currentEwkView)) {
1308                 // go back to previous WKPage
1309                 ewk_view_back(This->m_currentEwkView);
1310             } else {
1311                 // stop current WKPage
1312                 ewk_view_stop(This->m_currentEwkView);
1313                 ecore_idler_add(windowCloseIdlerCallback, This);
1314             }
1315         }
1316         LogDebug("ignore");
1317         WKFramePolicyListenerIgnore(listener);
1318     }
1319 }
1320
1321 void ViewLogic::pageDecidePolicyForNewWindowActionCallback(
1322         WKPageRef page,
1323         WKFrameRef frame,
1324         WKFrameNavigationType /*navigationType*/,
1325         WKEventModifiers /*modifiers*/,
1326         WKEventMouseButton /*mouseButton*/,
1327         WKURLRequestRef request,
1328         WKStringRef /*frameName*/,
1329         WKFramePolicyListenerRef listener,
1330         WKTypeRef /*userData*/,
1331         const void* clientInfo)
1332 {
1333     LogDebug("Accepting URL: " << ViewModule::Utils::toString(request));
1334     Assert(clientInfo);
1335
1336     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(clientInfo));
1337
1338     if (This->m_schemeSupport->filterURIByScheme(page,
1339                                                  frame,
1340                                                  request,
1341                                                  true,
1342                                                  This->m_model,
1343                                                  This->m_window))
1344     {
1345         WKFramePolicyListenerUse(listener);
1346     }
1347     else
1348     {
1349         // scheme handled
1350         WKFramePolicyListenerIgnore(listener);
1351     }
1352 }
1353
1354 void ViewLogic::contextmenuCustomizeCallback(
1355         void* data,
1356         Evas_Object* /*obj*/,
1357         void* eventInfo)
1358 {
1359     LogDebug("contextmenuCustomizeCallback called");
1360     Assert(data);
1361     Assert(eventInfo);
1362     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1363     Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1364     if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1365         (This->m_model->SettingList.Get().getContextMenu()
1366             == ContextMenu_Disable))
1367     {
1368         LogDebug("ContextMenu Disable!!");
1369         for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1370             Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1371             Assert(item);
1372             ewk_context_menu_item_remove(menu, item);
1373         }
1374     } else {
1375         LogDebug("ContextMenu Enable!!");
1376         for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1377             Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1378             Assert(item);
1379             Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1380
1381             switch (tag) {
1382                 case kWKContextMenuItemTagOpenImageInNewWindow:
1383                     ewk_context_menu_item_remove(menu, item);
1384                     break;
1385                 default:
1386                     idx++;
1387                     break;
1388             }
1389         }
1390     }
1391 }
1392
1393 void ViewLogic::formSubmitCallback(
1394         void* /*data*/,
1395         Evas_Object* /*obj*/,
1396         void* eventInfo)
1397 {
1398     LogDebug("formSubmitCallback called");
1399     Assert(eventInfo);
1400     Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1401
1402     const char* uri = ewk_form_data_url_get(formData);
1403     if (!uri) {
1404         LogError("URL is empty");
1405         return;
1406     }
1407
1408     Eina_Hash* userData = ewk_form_data_values_get(formData);
1409     ViewModule::PasswordSupport::submitClicked(uri, userData);
1410 }
1411
1412 void ViewLogic::geolocationPermissionRequestCallback(
1413         void* /*data*/,
1414         Evas_Object* /*obj*/,
1415         void* eventInfo)
1416 {
1417     LogDebug("geolocationPermissionRequestCallback called");
1418     Assert(eventInfo);
1419     ViewModule::GeolocationSupport::Webkit2::
1420         geolocationPermissionRequest(eventInfo);
1421     return;
1422 }
1423
1424 void ViewLogic::notificationShowCallback(
1425         void* data,
1426         Evas_Object* /*obj*/,
1427         void* eventInfo)
1428 {
1429     LogDebug("notificationShowCallback called");
1430     Assert(data);
1431     ViewLogic* This = static_cast<ViewLogic*>(data);
1432
1433     Assert(eventInfo);
1434     Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1435
1436     using namespace ViewModule::WebNotification;
1437
1438     WebNotificationDataPtr notiData(
1439             new WebNotificationData(
1440                 This->m_model,
1441                 ewk_notification_id_get(noti)));
1442
1443     DPL::OptionalString string =
1444         DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1445     if (!string.IsNull()) {
1446         notiData->m_iconURL = DPL::ToUTF8String(*string);
1447     }
1448     string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1449     if (!string.IsNull()) {
1450         notiData->m_title = DPL::ToUTF8String(*string);
1451     }
1452     string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1453     if (!string.IsNull()) {
1454         notiData->m_body = DPL::ToUTF8String(*string);
1455     }
1456
1457     LogInfo("notification id : " << notiData->m_id);
1458     LogInfo("notification iconURL : " << notiData->m_iconURL);
1459     LogInfo("notification title : " << notiData->m_title);
1460     LogInfo("notification body : " << notiData->m_body);
1461
1462     showWebNotification(notiData);
1463     ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1464 }
1465
1466 void ViewLogic::notificationCancelCallback(
1467         void* /*data*/,
1468         Evas_Object* /*obj*/,
1469         void* /*eventInfo*/)
1470 {
1471     LogDebug("notificationCancelCallback called");
1472 }
1473
1474 void ViewLogic::notificationPermissionRequestCallback(
1475         void* data,
1476         Evas_Object* /*obj*/,
1477         void* eventInfo)
1478 {
1479     LogDebug("notificationPermissionRequestCallback called");
1480     Assert(data);
1481     ViewLogic* This = static_cast<ViewLogic*>(data);
1482
1483     Assert(eventInfo);
1484     Ewk_Notification_Permission_Request* request =
1485         static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1486     ewk_notification_permission_request_response(
1487         This->m_ewkContext,
1488         request,
1489         EINA_TRUE);
1490     return;
1491 }
1492
1493 void ViewLogic::vibrationVibrateCallback(
1494         void* data,
1495         Evas_Object* /*obj*/,
1496         void* eventInfo)
1497 {
1498     LogDebug("vibrationVibrateCallback called");
1499     Assert(data);
1500     ViewLogic* This = static_cast<ViewLogic*>(data);
1501
1502     Assert(eventInfo);
1503     const long vibrationTime = *(static_cast<const long*>(eventInfo));
1504     This->m_vibrationSupport->startVibration(vibrationTime);
1505     return;
1506 }
1507
1508 void ViewLogic::vibrationCancelCallback(
1509         void* data,
1510         Evas_Object* /*obj*/,
1511         void* /*eventInfo*/)
1512 {
1513     LogDebug("vibrationCancelCallback called");
1514     Assert(data);
1515     ViewLogic* This = static_cast<ViewLogic*>(data);
1516     This->m_vibrationSupport->stopVibration();
1517     return;
1518 }
1519
1520 // EWK Orientation Callback
1521 Eina_Bool ViewLogic::orientationLockCallback(
1522         Evas_Object* obj,
1523         Eina_Bool needLock,
1524         int orientation,
1525         void* data)
1526 {
1527     LogDebug("orientationLockCallback called");
1528     Assert(data);
1529     ViewLogic* This = static_cast<ViewLogic*>(data);
1530
1531     // current implementation doesn't use lock value
1532     needLock;
1533     if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1534         LogDebug("orientation is portrait-primary");
1535         elm_win_rotation_with_resize_set(This->m_window, 0);
1536         ewk_view_orientation_send(obj, 0);
1537     } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1538         LogDebug("orientation is landscape-primary");
1539         elm_win_rotation_with_resize_set(This->m_window, 270);
1540         ewk_view_orientation_send(obj, 90);
1541     } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1542         LogDebug("orientation is portrait-secondary");
1543         elm_win_rotation_with_resize_set(This->m_window, 180);
1544         ewk_view_orientation_send(obj, 180);
1545     } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1546         LogDebug("orientation is landscape-secondary");
1547         elm_win_rotation_with_resize_set(This->m_window, 90);
1548         ewk_view_orientation_send(obj, -90);
1549     } else {
1550         LogDebug("Wrong orientation is set");
1551         return EINA_FALSE;
1552     }
1553     return EINA_TRUE;
1554 }
1555
1556 void ViewLogic::didRunJavaScriptCallback(
1557         Evas_Object* /*obj*/,
1558         const char* result,
1559         void* /*userData*/)
1560 {
1561     LogInfo("didRunJavaScriptCallback called");
1562     LogInfo("result = " << result);
1563 }
1564
1565 void ViewLogic::backButtonCallback(void* data,
1566                                          Evas_Object * /*obj*/,
1567                                          void * /*event_info*/)
1568 {
1569     LogInfo("BackButtonCallback");
1570     Assert(data);
1571
1572     ViewLogic* This = static_cast<ViewLogic*>(data);
1573
1574     if (WKPageCanGoBack(ewk_view_WKPage_get(This->m_currentEwkView))) {
1575         WKPageGoBack(ewk_view_WKPage_get(This->m_currentEwkView));
1576     } else {
1577         if (1 >= This->m_ewkViewList.size()) {
1578             // If there is no previous page, widget move to backgroud.
1579             LogInfo("Widget move to backgroud");
1580             elm_win_lower(This->m_window);
1581         } else {
1582             // Back to previous webview
1583             LogInfo("Widget move to previous webview");
1584             ecore_idler_add(windowCloseIdlerCallback, This);
1585         }
1586     }
1587 }
1588
1589 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
1590 {
1591     LogDebug("closeIdlerCallback");
1592     ViewLogic* This = static_cast<ViewLogic*>(data);
1593     This->windowClose();
1594     return ECORE_CALLBACK_CANCEL;
1595 }
1596
1597 void ViewLogic::processDidCrashCallback(WKPageRef /*page*/,
1598                                         const void* clientInfo)
1599 {
1600     LogInfo("processDidCrashCallback");
1601
1602     ViewLogic const * const view =
1603             static_cast<ViewLogic const * const>(clientInfo);
1604     if (view->m_cbs->webCrash) {
1605         view->m_cbs->webCrash(view->m_cbsData);
1606     }
1607 }
1608
1609 int ViewLogic::appcoreLowMemoryCallback(void *data)
1610 {
1611     LogInfo("appcoreLowMemoryCallback");
1612     Assert(data);
1613     ViewLogic* This = static_cast<ViewLogic*>(data);
1614
1615     if (NULL == This->m_ewkContext) {
1616         LogInfo("ewk isn't initialize at this moment");
1617     } else {
1618         ewk_context_cache_clear(This->m_ewkContext);
1619         ewk_context_notify_low_memory(This->m_ewkContext);
1620     }
1621
1622     return 0;
1623 }
1624
1625 void ViewLogic::didRecieveMessageFromInjectedBundle(
1626         const char* name,
1627         const char* /*body*/)
1628 {
1629     LogDebug("did recive message " << name);
1630 }
1631
1632 void ViewLogic::didReceiveSynchronousMessage(
1633         const char* name,
1634         const char* body,
1635         char** returnData)
1636 {
1637     LogDebug("didReceiveSynchronousMessage called");
1638     Assert(name);
1639     Assert(returnData);
1640
1641     if (!body) {
1642         LogDebug("body is empty");
1643         *returnData = NULL;
1644         return;
1645     }
1646     if (!strcmp(name, willSendMessageName)) {
1647         LogDebug("received : " << willSendMessageName);
1648
1649         bool is_xhr = true; //Webkit2 should inform if it is xhr
1650         DPL::OptionalString ret =
1651             requestWillSend(DPL::FromUTF8String(body), is_xhr);
1652         if (ret.IsNull()) {
1653             LogError("Wrong type received");
1654             *returnData = NULL;
1655         } else {
1656             LogDebug("returning uri: " << ret);
1657             *returnData = strdup(DPL::ToUTF8String(*ret).c_str());
1658         }
1659     } else if (!strcmp(name, uriChangedMessageName)) {
1660         LogDebug("received : " << uriChangedMessageName);
1661         std::string ret = requestUriChanged(DPL::FromUTF8String(body));
1662         *returnData =  strdup(ret.c_str());
1663     }
1664 }
1665
1666 DPL::Optional<DPL::String> ViewLogic::requestWillSend(
1667         const DPL::String& inputURI,
1668         bool is_xhr)
1669 {
1670     DPL::Optional<DPL::String> uri =
1671         ViewModule::UriSupport::localizeURI(inputURI, m_model);
1672
1673     if (uri.IsNull())
1674     {
1675         LogDebug("uri is empty");
1676         return uri;
1677     }
1678
1679     // check ACE, WARP
1680     if (!ViewModule::SecuritySupport::filterURIBySecurity(uri, is_xhr, m_model))
1681     {
1682         // set blocked uri to open browser later
1683         m_blockedUri = DPL::ToUTF8String(*uri);
1684         LogInfo("set blocked uri to open browser later : " << m_blockedUri);
1685         return DPL::Optional<DPL::String>::Null;
1686     }
1687
1688     // check roaming state for external scheme
1689     if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
1690     {
1691         LogInfo("TizenWebApp does not need to check roaming status!");
1692     }
1693     else if (!ViewModule::SecuritySupport::filterURIByRoaming(uri))
1694     {
1695         LogDebug("Request was blocked by roaming settings: " << uri);
1696         return DPL::Optional<DPL::String>::Null;
1697     }
1698
1699     return uri;
1700 }
1701
1702 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
1703 {
1704     using namespace ViewModule::SecuritySupport;
1705
1706     std::string url = DPL::ToUTF8String(changedURL);
1707     LogInfo("URL = [" << url << "]");
1708     m_emptyView = false;
1709
1710     // check WARP
1711     // If url is same to URICHANGE_BLOCKED_URL,
1712     // this url has been already blocked by willsend.
1713     // So current page should be moved to previous page
1714     if (url == URICHANGE_BLOCKED_URL)
1715     {
1716         if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
1717         {
1718             // block this page and open it in browser
1719             LogDebug("Request was blocked by WARP: " << url.c_str());
1720             if (!m_blockedUri.empty()) {
1721                 LogDebug("open browser : " << m_blockedUri);
1722                 bundle* bundleData = bundle_create();
1723                 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
1724                 appsvc_set_uri(bundleData, m_blockedUri.c_str());
1725                 CONTROLLER_POST_EVENT(
1726                     ApplicationLauncher,
1727                     ApplicationLauncherEvents::LaunchApplicationByAppService(
1728                         bundleData,
1729                         NULL,
1730                         NULL));
1731                 m_blockedUri = std::string();
1732             }
1733         }
1734         if (ewk_view_back_possible(m_currentEwkView)) {
1735             // go back to previous WKPage
1736             ewk_view_back(m_currentEwkView);
1737         } else {
1738             // stop current WKPage
1739             ewk_view_stop(m_currentEwkView);
1740             ecore_idler_add(windowCloseIdlerCallback, this);
1741         }
1742
1743         // This is used in case of returning previous page
1744         m_currentUri = url;
1745         return URICHANGE_PLUGIN_NO_CHANGE;
1746     }
1747
1748     m_currentUri = url;
1749
1750     // Check if this url with 'http' or 'https' is included in whitelist,
1751     // which has lists of accessible external documents and
1752     // used for ONLY Tizen app
1753     std::string matchedScheme;
1754     std::string matchedUri;
1755     pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
1756                                                  &matchedUri,
1757                                                  &matchedScheme);
1758     ViewModule::Scheme scheme(matchedScheme);
1759     if (scheme.GetType() == ViewModule::Scheme::HTTP ||
1760         scheme.GetType() == ViewModule::Scheme::HTTPS)
1761     {
1762         if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
1763             if (!checkWhitelist(url.c_str())) {
1764                 LogInfo("This uri is not included in white document list");
1765                 return URICHANGE_PLUGIN_STOP_ONLY;
1766             }
1767             LogInfo("This url is included in WhiteList");
1768         } else {
1769             // For WAC app, WRT should block access of device api
1770             // for external documents
1771             return URICHANGE_PLUGIN_STOP_ONLY;
1772         }
1773     }
1774
1775     // register javascript object for plugins to be used
1776     LogInfo("Register Plugin Objects");
1777     return URICHANGE_PLUGIN_RESTART;
1778 }
1779
1780 void ViewLogic::disconnectNetworkConnectionsFunction() {
1781     if (m_ewkContext) {
1782         LogDebug("disconnection network connections");
1783         // API needs Ewk_context
1784         // Re-open after merged below commit
1785         // http://slp-info.sec.samsung.net/gerrit/#change,48358
1786         // ewk_context_network_session_requests_cancel(m_ewkContext);
1787     }
1788 }
1789
1790 void ViewLogic::windowClose()
1791 {
1792     LogDebug("windowClose");
1793
1794     if (1 >= m_ewkViewList.size()) {
1795         if (m_cbs->windowClose) {
1796             m_cbs->windowClose(m_cbsData);
1797         }
1798     } else {
1799         // hide current ewkView
1800
1801         if (m_cbs->bufferUnset) {
1802             m_cbs->bufferUnset(m_currentEwkView, m_cbsData);
1803         }
1804         removeEwkView(m_currentEwkView);
1805
1806         // get latest ewkView
1807         m_currentEwkView = m_ewkViewList.back();
1808         WKPageRef page = ewk_view_WKPage_get(m_currentEwkView);
1809         WKFrameRef frame = WKPageGetMainFrame(page);
1810
1811         DPL::OptionalString frameURL = ViewModule::Utils::toString(frame);
1812         if (frameURL.IsNull()) {
1813             m_currentUri.clear();
1814             m_emptyView = true;
1815         } else {
1816             m_currentUri = DPL::ToUTF8String(*frameURL);
1817             m_emptyView = false;
1818         }
1819
1820         // resume ewkView
1821         /* In case we support many pages in parallel
1822            then view is not suspended*/
1823         //resumeEwkView(m_currentEwkView);
1824
1825         // show ewkView
1826         if (m_cbs->bufferSet) {
1827             m_cbs->bufferSet(m_currentEwkView, m_cbsData);
1828         }
1829     }
1830 }