Implement notification permission request
[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 <view_logic_scheme_support.h>
53 #include <view_logic_filesystem_support.h>
54 #include <view_logic_geolocation_support_webkit2.h>
55 #include <view_logic_usermedia_support.h>
56 #include <view_logic_web_notification_support.h>
57 #include <view_logic_web_storage_support.h>
58 #include "bundles/plugin_module_support.h"
59 #include <popup-runner/PopupInvoker.h>
60
61 #include <EWebKit2.h>
62 #include <js_overlay_types.h>
63 #include <i_runnable_widget_object.h>
64 #include <profiling_util.h>
65 #include <wrt-commons/custom-handler-dao-ro/common_dao_types.h>
66 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
67 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
68 #include <wrt-commons/custom-handler-dao-rw/custom_handler_dao.h>
69
70 #include <appsvc/appsvc.h>
71
72 namespace {
73 const char * const bundlePath = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
74 const char * const uriBlockedMessageName = "uri_block_msg";
75 const char * const uriChangedMessageName = "uri_changed_msg";
76 const char * const URICHANGE_PLUGIN_STOP_ONLY = "plugin_stop_only";
77 const char * const URICHANGE_PLUGIN_RESTART = "plugin_restart";
78 const char * const URICHANGE_PLUGIN_NO_CHANGE = "plugin_no_change";
79 const char * const URICHANGE_BLOCKED_URL = "null";
80 const char* PATTERN_URI_CHANGE = "^(([^:/\\?#]+)://[^\\?#]*)";
81 const int MAX_NUM_CONTEXT_MENU_ITEMS = 10;
82 // IME State value
83 const char * const IME_STATE_ON = "on";
84 const char * const IME_STATE_OFF = "off";
85
86 // WKPageLoaderClient
87 const char * const EWK_LOAD_STARTED = "load,started";
88 const char * const EWK_LOAD_FINISHED = "load,finished";
89 const char * const EWK_TITLE_CHANGED = "title,changed";
90 const char * const EWK_LOAD_PROGRESS = "load,progress";
91 const char * const EWK_LOAD_PROGRESS_FINISHED = "load,progress,finished";
92 const char * const EWK_PROCESS_CRASHED = "process,crashed";
93 // WKPageUIClient
94 const char * const EWK_CREATE_WINDOW = "create,window";
95 const char * const EWK_CLOSE_WINDOW = "close,window";
96 // WKPagePolicyClient
97 const char * const EWK_POLICY_NAVIGATION_DECIDE = "policy,navigation,decide";
98 const char * const EWK_POLICY_NEWWINDOW_DECIDE = "policy,newwindow,decide";
99 const char * const EWK_POLICY_RESPONSE_DECIDE = "policy,response,decide";
100 // WKPageContextMenuClient
101 const char * const EWK_CONTEXTMENU_CUSTOMIZE = "contextmenu,customize";
102 // WKPageFormClient
103 const char * const EWK_FORM_SUBMIT = "form,submit";
104 // EWK Geolocation Callback
105 const char * const EWK_REQUEST_GEOLOCATION_PERMISSION =
106     "request,geolocation,permission";
107 // EWK Notification Callback
108 const char * const EWK_NOTIFICATION_SHOW = "notification,show";
109 const char * const EWK_NOTIFICATION_CANCEL = "notification,cancel";
110 const char * const EWK_NOTIFICATION_PERMISSION_REQUEST =
111     "notification,permission,request";
112 // EWK Vibration Callback
113 const char * const EWK_VIBRATION_VIBRATE = "vibration,vibrate";
114 const char * const EWK_VIBRATION_CANCEL = "vibration,cancel";
115
116 const char * const EWK_CONTEXT_EXCEEDED_QUOATA  = "database,quota,exceeded";
117 const char * const EWK_FILESYSTEM_PERMISSION_REQUEST = "filesystem,permission,request";
118 const char * const EWK_FULLSCREEN_ENTER = "fullscreen,enterfullscreen";
119 const char * const EWK_FULLSCREEN_EXIT = "fullscreen,exitfullscreen";
120
121 // IME Callback
122 const char * const EWK_INPUTMETHOD_CHANGED = "inputmethod,changed";
123 const char * const EWK_EDITORCLIENT_IME_OPENED = "editorclient,ime,opened";
124 const char * const EWK_EDITORCLIENT_IME_CLOSED = "editorclient,ime,closed";
125
126 // EWK Usermedia Callback
127 const char * const EWK_USERMEDIA_PERMISSION_REQUEST = "usermedia,permission,request";
128
129 // Custom handlers
130 const char * const EWK_PROTOCOLHANDLER_REGISTRATION = "protocolhandler,registration,requested";
131 const char * const EWK_PROTOCOLHANDLER_ISREGISTERED = "protocolhandler,isregistered";
132 const char * const EWK_PROTOCOLHANDLER_UNREGISTRATION = "protocolhandler,unregistration,requested";
133 const char * const EWK_CONTENTHANDLER_REGISTRATION = "contenthandler,registration,requested";
134 const char * const EWK_CONTENTHANDLER_ISREGISTERED = "contenthandler,isregistered";
135 const char * const EWK_CONTENTHANDLER_UNREGISTRATION = "contenthandler,unregistration,requested";
136
137 const char PROTOCOL_HANDLER_ASK_MSG[] = "Add protocol?";
138 const char PROTOCOL_HANDLER_ASK_TITLE[] = "Add protocol";
139 const char PROTOCOL_HANDLER_ASK_REMEMBER[] = "Remember dicision";
140 const char CONTENT_HANDLER_ASK_MSG[] = "Add content?";
141 const char CONTENT_HANDLER_ASK_TITLE[] = "Add content";
142 const char CONTENT_HANDLER_AKS_REMEMBER[] = "Remember dicision";
143 }
144
145 ViewLogic::ViewLogic():
146     m_ewkContext(0),
147     m_currentEwkView(0),
148     m_window(NULL),
149     m_model(0),
150     m_cbs(new WRT::UserDelegates),
151     m_isBackgroundReload(false),
152     m_appsSupport(new ViewModule::AppsSupport()),
153     m_vibrationSupport(),
154     m_attachedToCustomHandlerDao(false)
155 {
156 }
157
158 ViewLogic::~ViewLogic ()
159 {
160     detachFromCustomHandlersDao();
161 }
162
163 void ViewLogic::createWebView(Ewk_Context* context,
164                               Evas_Object* window)
165 {
166     LogDebug("");
167     initializeEwkContext(context);
168     Assert(NULL != m_ewkContext);
169     Assert(window);
170     m_window = window;
171     createEwkView(evas_object_evas_get(m_window));
172 }
173
174 void ViewLogic::destroyWebView()
175 {
176     if (m_ewkContext) {
177         finalizeEwkContext();
178     }
179 }
180
181 void ViewLogic::initialize()
182 {
183     LogDebug("Initializing");
184     ApplicationLauncherSingleton::Instance().Touch();
185     appcore_set_event_callback(
186         APPCORE_EVENT_LOW_MEMORY,
187         &appcoreLowMemoryCallback,
188         this);
189 }
190
191 void ViewLogic::terminate()
192 {
193     LogDebug("terminating view logic");
194     if (m_model) {
195         hideWidget();
196     } else {
197         LogError("Widget model not created");
198     }
199     LogDebug("done");
200 }
201
202 void ViewLogic::prepareView(WidgetModel* m, const std::string &startUrl)
203 {
204     LogDebug("View prepare");
205
206     Assert(m);
207     m_model = m;
208     m_startUrl = ViewModule::UriSupport::getUri(m_model, startUrl);
209     Assert(NULL != m_ewkContext);
210     Assert(m_window);
211
212     ADD_PROFILING_POINT("initializeSupport", "start");
213     initializeSupport();
214     ADD_PROFILING_POINT("initializeSupport", "stop");
215     setStartPage();
216     ewkClientInit(m_currentEwkView);
217     ADD_PROFILING_POINT("prepareEwkView", "start");
218     prepareEwkView(m_currentEwkView);
219     ADD_PROFILING_POINT("prepareEwkView", "stop");
220     initializePluginLoading();
221 }
222
223 void ViewLogic::showWidget()
224 {
225     LogDebug("showing widget");
226     Assert(NULL != m_currentEwkView && "ewk_view not created at this point");
227     if (m_currentUri.empty()) {
228         LogError("Localized current URI doesn't exist");
229         return;
230     }
231
232     LogInfo("m_currentUri: " << m_currentUri);
233
234     // load page
235     ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
236
237     if (!m_cbs->bufferSet.empty()) {
238         m_cbs->bufferSet(m_currentEwkView);
239     }
240 }
241
242 void ViewLogic::hideWidget()
243 {
244     LogDebug("hiding widget");
245     ViewModule::StorageSupport::deinitializeStorage(m_model);
246     m_appsSupport->deinitialize();
247
248     // temp
249     // m_vibrationSupport->deinitialize();
250
251     while (m_ewkViewList.size()) {
252         LogInfo("pop webview: " << m_ewkViewList.back());
253         removeEwkView(m_ewkViewList.back());
254     }
255     m_ewkViewList.clear();
256 }
257
258 void ViewLogic::suspendWidget()
259 {
260     LogInfo("Pausing widget");
261     Assert(m_model);
262
263     LogDebug("Request bundle to suspend");
264     PluginModuleSupport::suspend(m_ewkContext);
265
266     if (!m_currentEwkView) {
267         LogWarning("Cannot suspend widget without view");
268     } else {
269         suspendWebkit(m_currentEwkView);
270     }
271
272     evas_object_focus_set(m_currentEwkView, EINA_FALSE);
273
274     // call user callback
275     if (!m_cbs->suspend.empty()) {
276         m_cbs->suspend(true);
277     }
278 };
279
280 void ViewLogic::resumeWidget()
281 {
282     LogInfo("Resume widget");
283     Assert(m_model);
284
285     LogDebug("Request bundle to resume");
286     PluginModuleSupport::resume(m_ewkContext);
287
288     if (m_currentEwkView) {
289         resumeWebkit(m_currentEwkView);
290     }
291
292    /* window system team recomend removing this win_raise code. */
293     /*
294     if (m_window) {
295         elm_win_raise(m_window);
296     }
297     */
298     evas_object_focus_set(m_currentEwkView, EINA_TRUE);
299
300     // call user callback
301     if (!m_cbs->resume.empty()) {
302         m_cbs->resume(true);
303     }
304 };
305
306 void ViewLogic::resetWidget()
307 {
308     LogInfo("Resetting Widget");
309
310     // check if already created webview exists
311     if (!m_ewkViewList.size()) {
312         // create new webview
313         createEwkView(evas_object_evas_get(m_window));
314         setStartPage();
315         ewkClientInit(m_currentEwkView);
316         prepareEwkView(m_currentEwkView);
317     } else {
318         // check if current url is service url for this tizen service
319         std::string requestedUri =
320                 ViewModule::UriSupport::getUri(m_model, m_startUrl);
321         DPL::OptionalString servicedUri = ViewModule::UriSupport::localizeURI(
322                 DPL::FromUTF8String(requestedUri.c_str()),
323                 m_model);
324
325         const char* currentUri = ewk_view_url_get(m_currentEwkView);
326         if (!currentUri && 0 == strlen(currentUri)) {
327             LogError("Fail to get uri from ewk_view_url_get");
328             return;
329         }
330
331         // webview activated
332         PluginModuleSupport::resume(m_ewkContext);
333         resumeWebkit(m_currentEwkView);
334         if (DPL::ToUTF8String(*servicedUri) == currentUri) {
335             LogInfo("current page is raised");
336             // set only encoded bundle
337             double scale = elm_config_scale_get();
338             PluginModuleSupport::setCustomProperties(
339                 m_ewkContext,
340                 &scale,
341                 ApplicationDataSingleton::Instance().getEncodedBundle());
342             PluginModuleSupport::dispatchJavaScriptEvent(
343                 m_ewkContext,
344                 WrtPlugins::W3C::ServiceCustomEvent,
345                 NULL);
346         } else {
347             LogInfo("service page is loaded");
348             m_currentUri = DPL::ToUTF8String(*servicedUri);
349             ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
350         }
351         elm_win_activate(m_window);
352         evas_object_focus_set(m_currentEwkView, EINA_TRUE);
353     }
354
355     // call user callback
356     if (!m_cbs->reset.empty()) {
357         m_cbs->reset(true);
358     }
359     if (!m_cbs->bufferSet.empty()) {
360         m_cbs->bufferSet(m_currentEwkView);
361     }
362 }
363
364 void ViewLogic::backward()
365 {
366     if (ewk_view_back_possible(m_currentEwkView)) {
367         ewk_view_back(m_currentEwkView);
368     } else {
369         if (1 >= m_ewkViewList.size()) {
370             // If there is no previous page, widget move to backgroud.
371             LogInfo("Widget move to backgroud");
372             elm_win_lower(m_window);
373         } else {
374             // Back to previous webview
375             LogInfo("Widget move to previous webview");
376             ecore_idler_add(windowCloseIdlerCallback, this);
377         }
378     }
379 }
380
381 void ViewLogic::reloadStartPage()
382 {
383     LogInfo("Reload Start Page");
384     // prevent fail to load plugin bundle side
385     m_isBackgroundReload = true;
386     PluginModuleSupport::resume(m_ewkContext);
387
388     if (m_ewkViewList.size() != 0) {
389         while (m_ewkViewList.size() > 0) {
390             if (!m_cbs->bufferUnset.empty()) {
391                 m_cbs->bufferUnset(m_currentEwkView);
392             }
393             removeEwkView(m_currentEwkView);
394         }
395     }
396
397     // create new webview
398     createEwkView(evas_object_evas_get(m_window));
399     ewkClientInit(m_currentEwkView);
400
401     setStartPage();
402     prepareEwkView(m_currentEwkView);
403     initializePluginLoading();
404
405     // load page
406     ewk_view_url_set(m_currentEwkView, m_currentUri.c_str());
407
408     // show ewkView
409     if (!m_cbs->bufferSet.empty()) {
410         m_cbs->bufferSet(m_currentEwkView);
411     }
412     LogInfo("Reloading Start Page is done!");
413 }
414
415 Evas_Object* ViewLogic::getCurrentWebview()
416 {
417     LogInfo("get current webview");
418     return m_currentEwkView;
419 }
420
421 void ViewLogic::fireJavascriptEvent(int event, void* data)
422 {
423     PluginModuleSupport::dispatchJavaScriptEvent(
424         m_ewkContext,
425         static_cast<WrtPlugins::W3C::CustomEventType>(event),
426         data);
427 }
428
429 void ViewLogic::setUserCallbacks(const WRT::UserDelegatesPtr& cbs)
430 {
431     m_cbs = cbs;
432 }
433
434 void ViewLogic::initializeEwkContext(Ewk_Context* newEwkContext)
435 {
436     LogInfo("initializeEwkContext called");
437     Assert(newEwkContext && "Ewk_Context provided can not be null");
438     // bundle callback setting
439     ewk_context_message_from_injected_bundle_callback_set(
440         newEwkContext,
441         contextMessageFromInjectedBundleCallback,
442         static_cast<void*>(this));
443
444     // proxy server setting
445     char *proxyAddress = vconf_get_str(VCONFKEY_NETWORK_PROXY);
446     if ((!proxyAddress) || (strlen(proxyAddress) == 0)
447         || (strstr(proxyAddress, "0.0.0.0")))
448     {
449         LogInfo("proxy address is empty");
450         ewk_context_proxy_uri_set(newEwkContext, NULL);
451     } else {
452         LogInfo("proxy address [" << proxyAddress << "]");
453         ewk_context_proxy_uri_set(newEwkContext,  proxyAddress);
454     }
455
456     if (proxyAddress) {
457         free(proxyAddress);
458         proxyAddress = NULL;
459     }
460
461     // theme setting
462     const char *theme = elm_theme_get(NULL);
463     if (theme) {
464         m_theme = theme;
465         LogInfo("theme is " << m_theme);
466     }
467
468     // Ewk download callback (WKContextDownloadClient)
469     ewk_context_did_start_download_callback_set(
470         newEwkContext,
471         didStartDownloadCallback,
472         this);
473
474     // set to member value
475     m_ewkContext = newEwkContext;
476 }
477
478 void ViewLogic::finalizeEwkContext()
479 {
480     LogInfo("finalizeEwkContext called");
481     ewk_context_message_from_injected_bundle_callback_set(
482             m_ewkContext,
483             NULL,
484             NULL);
485 //    ewk_context_delete(m_ewkContext);
486 //    m_ewkContext = 0;
487 }
488
489 void ViewLogic::initializeSupport()
490 {
491     // set local stroage database path
492     WrtDB::WidgetDAOReadOnly dao(m_model->TizenId);
493     ewk_context_web_storage_path_set(m_ewkContext,
494                                      dao.getPrivateLocalStoragePath().c_str());
495     m_schemeSupport.reset(new SchemeSupport(m_model->Type.Get().appType));
496     ViewModule::StorageSupport::initializeStorage(m_model);
497     m_appsSupport->initialize(m_model);
498     m_securityOriginSupport.reset(new ViewModule::SecurityOriginSupport(m_model));
499
500     // temp
501     // m_vibrationSupport->initialize();
502 }
503
504 void ViewLogic::initializePluginLoading()
505 {
506     // inform wrt information for plugin loading to web process
507     PluginModuleSupport::start(
508         m_ewkContext,
509         m_model->TizenId,
510         elm_config_scale_get(),
511         ApplicationDataSingleton::Instance().getEncodedBundle(),
512         m_theme.c_str(),
513         m_model->SettingList.Get().isEncrypted());
514 }
515
516 void ViewLogic::ewkClientInit(Evas_Object *wkView) {
517     Assert(NULL != wkView && "ewk_view not created at this point");
518     // WKPageLoaderClient
519     evas_object_smart_callback_add(
520         wkView,
521         EWK_LOAD_STARTED,
522         loadStartedCallback,
523         this);
524     evas_object_smart_callback_add(
525         wkView,
526         EWK_LOAD_FINISHED,
527         loadFinishedCallback,
528         this);
529     evas_object_smart_callback_add(
530         wkView,
531         EWK_TITLE_CHANGED,
532         titleChangedCallback,
533         this);
534     evas_object_smart_callback_add(
535         wkView,
536         EWK_LOAD_PROGRESS,
537         loadProgressCallback,
538         this);
539     evas_object_smart_callback_add(
540         wkView,
541         EWK_LOAD_PROGRESS_FINISHED,
542         loadProgressFinishedCallback,
543         this);
544     evas_object_smart_callback_add(
545         wkView,
546         EWK_PROCESS_CRASHED,
547         processCrashedCallback,
548         this);
549
550     // WKPageUIClient
551     evas_object_smart_callback_add(
552         wkView,
553         EWK_CREATE_WINDOW,
554         createWindowCallback,
555         this);
556     evas_object_smart_callback_add(
557         wkView,
558         EWK_CLOSE_WINDOW,
559         closeWindowCallback,
560         this);
561
562     // WKPagePolicyClient
563     evas_object_smart_callback_add(
564         wkView,
565         EWK_POLICY_NAVIGATION_DECIDE,
566         policyNavigationDecideCallback,
567         this);
568     evas_object_smart_callback_add(
569         wkView,
570         EWK_POLICY_NEWWINDOW_DECIDE,
571         policyNewWindowDecideCallback,
572         this);
573     evas_object_smart_callback_add(
574         wkView,
575         EWK_POLICY_RESPONSE_DECIDE,
576         pageResponseDecideCallback,
577         this);
578
579     // WKPageContextMenuClient
580     evas_object_smart_callback_add(
581         wkView,
582         EWK_CONTEXTMENU_CUSTOMIZE,
583         contextmenuCustomizeCallback,
584         this);
585
586     // WKPageFormClient
587     evas_object_smart_callback_add(
588         wkView,
589         EWK_FORM_SUBMIT,
590         formSubmitCallback,
591         this);
592
593     // EWK Geolocation Callback
594     evas_object_smart_callback_add(
595         wkView,
596         EWK_REQUEST_GEOLOCATION_PERMISSION,
597         geolocationPermissionRequestCallback,
598         this);
599
600     // EWK Notification Callback
601     evas_object_smart_callback_add(
602         wkView,
603         EWK_NOTIFICATION_SHOW,
604         notificationShowCallback,
605         this);
606     evas_object_smart_callback_add(
607         wkView,
608         EWK_NOTIFICATION_CANCEL,
609         notificationCancelCallback,
610         this);
611     evas_object_smart_callback_add(
612         wkView,
613         EWK_NOTIFICATION_PERMISSION_REQUEST,
614         notificationPermissionRequestCallback,
615         this);
616
617     // EWK Vibration Callback
618     evas_object_smart_callback_add(
619         wkView,
620         EWK_VIBRATION_VIBRATE,
621         vibrationVibrateCallback,
622         this);
623     evas_object_smart_callback_add(
624         wkView,
625         EWK_VIBRATION_CANCEL,
626         vibrationCancelCallback,
627         this);
628     evas_object_smart_callback_add(
629         wkView,
630         EWK_CONTEXT_EXCEEDED_QUOATA,
631         databaseUsagePermissionRequestCallback,
632         this);
633     evas_object_smart_callback_add(
634         wkView,
635         EWK_FILESYSTEM_PERMISSION_REQUEST,
636         fileSystemPermissionRequestCallback,
637         this);
638
639     // EWK Orientation Callback
640     //ewk_view_orientation_lock_callback_set(
641     //    wkView,
642     //     orientationLockCallback,
643     //     this);
644
645     // Fullscreen API callbacks
646     evas_object_smart_callback_add(
647         wkView,
648         EWK_FULLSCREEN_ENTER,
649         enterFullscreenCallback,
650         this);
651     evas_object_smart_callback_add(
652         wkView,
653         EWK_FULLSCREEN_EXIT,
654         exitFullscreenCallback,
655         this);
656
657
658     // when ime start to be showed on the webview,
659     // this callback will be called
660     evas_object_smart_callback_add(
661         wkView,
662         EWK_INPUTMETHOD_CHANGED,
663         imeChangedCallback,
664         this);
665
666     // this callback will be called
667     //  when ime finishes to be showed on the webview
668     // "event_info" arg of this callback is always NULL point
669     // if web content should know size of ime,
670     //  use "inputmethod,changed" instead of this.
671     //
672     evas_object_smart_callback_add(
673         wkView,
674         EWK_EDITORCLIENT_IME_OPENED,
675         imeOpenedCallback,
676         this);
677
678     // when ime finished to be hidden,
679     // this callback will be called
680     evas_object_smart_callback_add(
681         wkView,
682         EWK_EDITORCLIENT_IME_CLOSED,
683         imeClosedCallback,
684         this);
685
686     // usermedia callback
687     evas_object_smart_callback_add(
688         wkView,
689         EWK_USERMEDIA_PERMISSION_REQUEST,
690         usermediaPermissionRequestCallback,
691         this);
692
693     // custom content/scheme handlers
694     evas_object_smart_callback_add(
695         wkView,
696         EWK_PROTOCOLHANDLER_REGISTRATION,
697         protocolHandlerRegistrationCallback,
698         this);
699     evas_object_smart_callback_add(
700         wkView,
701         EWK_PROTOCOLHANDLER_ISREGISTERED,
702         protocolHandlerIsRegisteredCallback,
703         this);
704     evas_object_smart_callback_add(
705         wkView,
706         EWK_PROTOCOLHANDLER_UNREGISTRATION,
707         protocolHandlerUnregistrationCallback,
708         this);
709
710     evas_object_smart_callback_add(
711         wkView,
712         EWK_CONTENTHANDLER_REGISTRATION,
713         contentHandlerRegistrationCallback,
714         this);
715     evas_object_smart_callback_add(
716         wkView,
717         EWK_CONTENTHANDLER_ISREGISTERED,
718         contentHandlerIsRegisteredCallback,
719         this);
720     evas_object_smart_callback_add(
721         wkView,
722         EWK_CONTENTHANDLER_UNREGISTRATION,
723         contentHandlerUnregistrationCallback,
724         this);
725 }
726
727 void ViewLogic::ewkClientDeinit(Evas_Object *wkView) {
728     LogDebug("ewkClientDeinit");
729     Assert(NULL != wkView && "ewk_view not created at this point");
730
731     // WKPageLoaderClient
732     evas_object_smart_callback_del(
733         wkView,
734         EWK_LOAD_STARTED,
735         loadStartedCallback);
736     evas_object_smart_callback_del(
737         wkView,
738         EWK_LOAD_FINISHED,
739         loadFinishedCallback);
740     evas_object_smart_callback_del(
741         wkView,
742         EWK_TITLE_CHANGED,
743         titleChangedCallback);
744     evas_object_smart_callback_del(
745         wkView,
746         EWK_LOAD_PROGRESS,
747         loadProgressCallback);
748     evas_object_smart_callback_del(
749         wkView,
750         EWK_LOAD_PROGRESS_FINISHED,
751         loadProgressFinishedCallback);
752     evas_object_smart_callback_del(
753         wkView,
754         EWK_PROCESS_CRASHED,
755         loadProgressCallback);
756
757     // WKPageUIClient
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     // WKPagePolicyClient
768     evas_object_smart_callback_del(
769         wkView,
770         EWK_POLICY_NAVIGATION_DECIDE,
771         policyNavigationDecideCallback);
772     evas_object_smart_callback_del(
773         wkView,
774         EWK_POLICY_NEWWINDOW_DECIDE,
775         policyNewWindowDecideCallback);
776     evas_object_smart_callback_del(
777         wkView,
778         EWK_POLICY_RESPONSE_DECIDE,
779         pageResponseDecideCallback);
780
781     // WKPageContextMenuClient
782     evas_object_smart_callback_del(
783         wkView,
784         EWK_CONTEXTMENU_CUSTOMIZE,
785         contextmenuCustomizeCallback);
786
787     // WKPageFormClient
788     evas_object_smart_callback_del(
789         wkView,
790         EWK_FORM_SUBMIT,
791         formSubmitCallback);
792
793     // EWK Geolocation Callback
794     evas_object_smart_callback_del(
795         wkView,
796         EWK_REQUEST_GEOLOCATION_PERMISSION,
797         geolocationPermissionRequestCallback);
798
799     // EWK Notification Callback
800     evas_object_smart_callback_del(
801         wkView,
802         EWK_NOTIFICATION_SHOW,
803         notificationShowCallback);
804     evas_object_smart_callback_del(
805         wkView,
806         EWK_NOTIFICATION_CANCEL,
807         notificationCancelCallback);
808     evas_object_smart_callback_del(
809         wkView,
810         EWK_NOTIFICATION_PERMISSION_REQUEST,
811         notificationPermissionRequestCallback);
812
813     // EWK Vibration Callback
814     evas_object_smart_callback_del(
815         wkView,
816         EWK_VIBRATION_VIBRATE,
817         vibrationVibrateCallback);
818     evas_object_smart_callback_del(
819         wkView,
820         EWK_VIBRATION_CANCEL,
821         vibrationCancelCallback);
822
823     evas_object_smart_callback_del(
824         wkView,
825         EWK_CONTEXT_EXCEEDED_QUOATA,
826         databaseUsagePermissionRequestCallback);
827     evas_object_smart_callback_del(
828         wkView,
829         EWK_FILESYSTEM_PERMISSION_REQUEST,
830         fileSystemPermissionRequestCallback);
831
832     // EWK Orientation Callback
833     //ewk_view_orientation_lock_callback_set(
834     //    wkView,
835     //    NULL,
836     //    NULL);
837
838     // ime change/show/hide callback
839     evas_object_smart_callback_del(
840         wkView,
841         EWK_INPUTMETHOD_CHANGED,
842         imeChangedCallback);
843     evas_object_smart_callback_del(
844         wkView,
845         EWK_EDITORCLIENT_IME_OPENED,
846         imeOpenedCallback);
847     evas_object_smart_callback_del(
848         wkView,
849         EWK_EDITORCLIENT_IME_CLOSED,
850         imeClosedCallback);
851
852     // usermedia callback
853     evas_object_smart_callback_del(
854         wkView,
855         EWK_USERMEDIA_PERMISSION_REQUEST,
856         usermediaPermissionRequestCallback);
857
858     // custom content/scheme handlers
859     evas_object_smart_callback_del(
860         wkView,
861         EWK_PROTOCOLHANDLER_REGISTRATION,
862         protocolHandlerRegistrationCallback);
863     evas_object_smart_callback_del(
864         wkView,
865         EWK_PROTOCOLHANDLER_ISREGISTERED,
866         protocolHandlerIsRegisteredCallback);
867     evas_object_smart_callback_del(
868         wkView,
869         EWK_PROTOCOLHANDLER_UNREGISTRATION,
870         protocolHandlerUnregistrationCallback);
871
872     evas_object_smart_callback_del(
873         wkView,
874         EWK_CONTENTHANDLER_REGISTRATION,
875         contentHandlerRegistrationCallback);
876     evas_object_smart_callback_del(
877         wkView,
878         EWK_CONTENTHANDLER_ISREGISTERED,
879         contentHandlerIsRegisteredCallback);
880     evas_object_smart_callback_del(
881         wkView,
882         EWK_CONTENTHANDLER_UNREGISTRATION,
883         contentHandlerUnregistrationCallback);
884 }
885
886 void ViewLogic::createEwkView(Evas* canvas)
887 {
888     LogDebug("createEwkVeiw");
889     Assert(canvas);
890     ADD_PROFILING_POINT("ewk_view_add_with_context", "start");
891     Evas_Object* newEwkView = ewk_view_add_with_context(
892         canvas,
893         m_ewkContext);
894     ADD_PROFILING_POINT("ewk_view_add_with_context", "stop");
895
896     if (!newEwkView) {
897         LogError("WKView creation failed");
898         Assert(false);
899     }
900
901     // set cookie policy
902     // even arguments pass the ewkContext, this API should be called
903     // after webkit Evas_Object is created
904     Ewk_Cookie_Manager *ewkCookieManager;
905     ewkCookieManager =
906         ewk_context_cookie_manager_get(m_ewkContext);
907     ewk_cookie_manager_accept_policy_set(ewkCookieManager,
908                            EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
909
910     LogInfo("push webview: " << newEwkView);
911     m_ewkViewList.push_back(newEwkView);
912     m_currentEwkView = newEwkView;
913 }
914
915 void ViewLogic::setStartPage()
916 {
917     /* Start URI (as other uris) is now localized
918      * on WebProcess side */
919     m_currentUri = m_startUrl;
920 }
921
922 void ViewLogic::prepareEwkView(Evas_Object *wkView)
923 {
924     LogDebug("prepareEwkView called");
925     Assert(wkView);
926     Ewk_Settings* settings = ewk_view_settings_get(wkView);
927
928     // set user agent
929     std::string customUserAgent = m_model->SettingList.Get().getUserAgent();
930     if (customUserAgent.empty()) {
931         auto userAgentString =
932             ViewModule::UserAgentSupport::getUserAgentFromVconf();
933         if (!userAgentString.empty()) {
934             LogDebug("Setting user agent as: " << userAgentString);
935             ewk_view_user_agent_set(wkView, userAgentString.c_str());
936         }
937     } else {
938         LogDebug("Setting  custom user agent as: " << customUserAgent);
939         ewk_view_user_agent_set(wkView, customUserAgent.c_str());
940     }
941
942     // set custom header : language
943     using namespace ViewModule::CustomHeaderSupport;
944     std::string customHeaderString = getValueByField(ACCEPT_LANGUAGE);
945     if (!customHeaderString.empty()) {
946         LogDebug("custom field=[" << ACCEPT_LANGUAGE << "]");
947         LogDebug("custom value=[" << customHeaderString << "]");
948         ewk_view_custom_header_add(wkView,
949                                    ACCEPT_LANGUAGE.c_str(),
950                                    customHeaderString.c_str());
951     }
952
953     // webkit NPAPI plugins is always on in wrt
954     ewk_settings_plugins_enabled_set(settings, EINA_TRUE);
955
956     // The followings are not implemeted yet by webkit2
957     //      ewk_view_setting_accelerated_compositing_enable_set(EINA_TRUE);
958     //      ewk_view_mode_set();
959     //      ewk_view_setting_enable_specified_plugin_set(EINA_TRUE, FLASH_MIME_TYPE);
960     //      ewk_view_setting_html5video_external_player_enable_set(EINA_FALSE);
961     //      ewk_view_show_ime_on_autofocus_set(EINA_TRUE);
962     //      elm_webview_show_magnifier_set(EINA_FALSE);
963     ewk_settings_javascript_enabled_set(settings, EINA_TRUE);
964     ewk_settings_loads_images_automatically_set(settings, EINA_TRUE);
965     ewk_settings_auto_fitting_set(settings, EINA_TRUE);
966
967     // disable zoom option when user click the input field
968     // this option is useful with the normal website
969     // for the make user friendly, disable auto zoom in the webapp
970     // The followings are not implemeted yet by webkit2
971     //      elm_webview_input_field_zoom_set(EINA_FALSE);
972
973     // set cookie database path
974     // The followings are not implemeted yet by webkit2
975     //      ewk_cookies_file_set(dao.getCookieDatabasePath().c_str()));
976
977     // set visibility to WebCore. This value will be used for html5.
978     // also, this value will be changed in the suspend, resume
979     // or create window, close window.
980     ewk_view_page_visibility_state_set(wkView,
981                                        EWK_PAGE_VISIBILITY_STATE_VISIBLE,
982                                        EINA_TRUE);
983 }
984
985 void ViewLogic::removeEwkView(Evas_Object *wkView)
986 {
987     LogInfo("removeEwkView called");
988     Assert(wkView);
989     Assert(0 != m_ewkViewList.size());
990
991     // unregister webview callbacks
992     ewkClientDeinit(wkView);
993
994     // suspend NPAPI plugin - Not implemented by Webkit2
995     //    ewk_view_pause_or_resume_plugins();
996     evas_object_del(wkView);
997     m_ewkViewList.remove(wkView);
998 }
999
1000 void ViewLogic::resumeEwkView(Evas_Object *wkView)
1001 {
1002     LogInfo("resumeEwkView called");
1003     Assert(wkView);
1004
1005     // register webview callback
1006     ewkClientInit(wkView);
1007
1008     // resume webkit
1009     resumeWebkit(wkView);
1010
1011     return;
1012 }
1013
1014 void ViewLogic::suspendEwkView(Evas_Object *wkView)
1015 {
1016     LogInfo("suspendEwkView called");
1017     Assert(wkView);
1018
1019     // suspend webkit
1020     suspendWebkit(wkView);
1021
1022     // unregister webview callbacks
1023     ewkClientDeinit(wkView);
1024
1025     return;
1026 }
1027
1028 void ViewLogic::resumeWebkit(Evas_Object *wkView)
1029 {
1030     LogDebug("resumeWebkit");
1031     Assert(wkView);
1032
1033     // resume NPAPI plugin
1034     // The followings are not implemeted yet by webkit2
1035     //      ewk_view_pause_or_resume_plugins(false);
1036     //      ewk_view_pause_or_resume_video_audio(false);
1037     //      ewk_view_javascript_resume();
1038     //      ewk_view_enable_render();
1039     //      ewk_view_reduce_plugins_frame_rate(false);
1040     ewk_view_resume(wkView);
1041     ewk_view_visibility_set(wkView, EINA_TRUE);
1042     ewk_view_page_visibility_state_set(wkView,
1043                                        EWK_PAGE_VISIBILITY_STATE_VISIBLE,
1044                                        EINA_FALSE);
1045     return;
1046 }
1047
1048 void ViewLogic::suspendWebkit(Evas_Object *wkView)
1049 {
1050     LogDebug("suspendWebkit");
1051     Assert(wkView);
1052
1053     // suspend the followings
1054     // The followings are not implemeted yet by webkit2
1055     //      ewk_view_pause_or_resume_plugins(true);
1056     //      ewk_view_pause_or_resume_video_audio(true);
1057
1058     // send visibility event to webpage
1059     ewk_view_page_visibility_state_set(wkView,
1060                                        EWK_PAGE_VISIBILITY_STATE_HIDDEN,
1061                                        EINA_FALSE);
1062     ewk_view_suspend(wkView);
1063     ewk_view_visibility_set(wkView, EINA_FALSE);
1064     return;
1065 }
1066
1067 void ViewLogic::contextMessageFromInjectedBundleCallback(
1068         const char* name,
1069         const char* body,
1070         char** returnData,
1071         void* clientInfo)
1072 {
1073     LogDebug("contextMessageFromInjectedBundleCallback called");
1074     Assert(clientInfo);
1075     ViewLogic* This = static_cast<ViewLogic*>(clientInfo);
1076     // didRecieveMessageFromInjectedBundleCallback - returnData is null
1077     // didReceiveSynchronousMessageCallback - returnData isn't null
1078     // WKContextInjectedBundleClient bundleClient = {
1079     //     kWKContextInjectedBundleClientCurrentVersion,
1080     //     static_cast<void*>(this),
1081     //     &didRecieveMessageFromInjectedBundleCallback,
1082     //     &didReceiveSynchronousMessageCallback
1083     // };
1084     if (NULL == returnData) {
1085         This->didRecieveMessageFromInjectedBundle(name, body);
1086     } else {
1087         This->didReceiveSynchronousMessage(name, body, returnData);
1088     }
1089 }
1090
1091 void ViewLogic::didStartDownloadCallback(
1092         const char* downloadUrl,
1093         void* data)
1094 {
1095     LogDebug("didStartDownloadCallback called");
1096     Assert(data);
1097     ViewLogic* This = static_cast<ViewLogic*>(data);
1098     Assert(downloadUrl);
1099     LogDebug("download url = " << downloadUrl);
1100     This->m_appsSupport->downloadRequest(
1101         downloadUrl,
1102         NULL,
1103         NULL);
1104 }
1105
1106 void ViewLogic::loadStartedCallback(
1107         void* data,
1108         Evas_Object* obj,
1109         void* /*eventInfo*/)
1110 {
1111     LogDebug("loadStartedCallback called");
1112     Assert(data);
1113     ViewLogic* This = static_cast<ViewLogic*>(data);
1114     evas_object_focus_set(This->m_currentEwkView, EINA_TRUE);
1115
1116     // call loadFinish callback to wrt-client
1117     if (!This->m_cbs->loadStart.empty()) {
1118         This->m_cbs->loadStart(obj);
1119     }
1120
1121 }
1122
1123 void ViewLogic::loadFinishedCallback(
1124         void* data,
1125         Evas_Object* obj,
1126         void* /*eventInfo*/)
1127 {
1128     LogDebug("loadFinishedCallback called");
1129     Assert(data);
1130     ViewLogic* This = static_cast<ViewLogic*>(data);
1131
1132     // Fill id/password
1133     const char* url = ewk_view_url_get(This->m_currentEwkView);
1134     if (NULL == url || strlen(url) == 0) {
1135         LogError("url is empty");
1136     } else {
1137         DPL::OptionalString jsOptionalString =
1138             ViewModule::PasswordSupport::jsForAutoFillData(url);
1139         if (jsOptionalString.IsNull()) {
1140             LogError("Fail to get JS String");
1141         } else {
1142             std::string jsStr = DPL::ToUTF8String(*jsOptionalString).c_str();
1143
1144             if(EINA_FALSE == ewk_view_script_execute(
1145                 This->m_currentEwkView,
1146                 jsStr.c_str(),
1147                 didRunJavaScriptCallback,
1148                 This))
1149             {
1150                 LogError("JS for auto fill data failed.");
1151             }
1152         }
1153     }
1154
1155     // call loadFinish callback to wrt-client
1156     if (!This->m_cbs->loadFinish.empty()) {
1157         This->m_cbs->loadFinish(obj);
1158     }
1159
1160     // set only encoded bundle
1161     double scale = elm_config_scale_get();
1162     PluginModuleSupport::setCustomProperties(
1163         This->m_ewkContext,
1164         &scale,
1165         ApplicationDataSingleton::Instance().getEncodedBundle());
1166     // check if 'appsevice' event is registed at the current frames.
1167     // If so, dispatch the event to frames.
1168     PluginModuleSupport::dispatchJavaScriptEvent(
1169         This->m_ewkContext,
1170         WrtPlugins::W3C::ServiceCustomEvent,
1171         NULL);
1172
1173     // In this case, widget is reloaded in the background.
1174     // After finished load, bundle should disconnent callback.
1175     if (This->m_isBackgroundReload) {
1176         PluginModuleSupport::suspend(This->m_ewkContext);
1177         ewk_view_suspend(This->m_currentEwkView);
1178         This->m_isBackgroundReload = false;
1179     }
1180 }
1181
1182 void ViewLogic::titleChangedCallback(
1183         void* data,
1184         Evas_Object* /*obj*/,
1185         void* eventInfo)
1186 {
1187     LogDebug("titleChangedCallback called");
1188     Assert(data);
1189     ViewLogic* This = static_cast<ViewLogic*>(data);
1190     Assert(eventInfo);
1191     const char* title = static_cast<char*>(eventInfo);
1192
1193     if (0 == strlen(title)) {
1194         LogDebug("title data is empty");
1195         return;
1196     }
1197     LogDebug("Title = [" << title << "]");
1198     This->m_schemeSupport->HandleTizenScheme(title,
1199                                              This->m_window,
1200                                              This->m_currentEwkView);
1201 }
1202
1203 void ViewLogic::loadProgressCallback(
1204         void* /*data*/,
1205         Evas_Object* /*obj*/,
1206         void* eventInfo)
1207 {
1208     double* progress = static_cast<double*>(eventInfo);
1209     LogDebug("didChangeProgressCallback progress = " << *progress);
1210 }
1211
1212 void ViewLogic::loadProgressFinishedCallback(
1213         void* data,
1214         Evas_Object* /*obj*/,
1215         void* /*eventInfo*/)
1216 {
1217     LogDebug("didFinishProgressCallback");
1218     Assert(data);
1219     ViewLogic const * const view = static_cast<ViewLogic const * const>(data);
1220     if (!view->m_cbs->progressFinish.empty()) {
1221         view->m_cbs->progressFinish();
1222     }
1223 }
1224
1225 void ViewLogic::processCrashedCallback(
1226         void* data,
1227         Evas_Object* /*obj*/,
1228         void* eventInfo)
1229 {
1230     LogInfo("processCrashedCallback");
1231     Assert(data);
1232     ViewLogic const * const view =
1233             static_cast<ViewLogic const * const>(data);
1234     if (!view->m_cbs->webCrash.empty()) {
1235         view->m_cbs->webCrash();
1236     }
1237     // This flag will be prevented exit() call in the Webkit side
1238     if (NULL != eventInfo) {
1239         *(static_cast<Eina_Bool*>(eventInfo)) = EINA_TRUE;
1240     }
1241 }
1242
1243 void ViewLogic::createWindowCallback(
1244         void* data,
1245         Evas_Object* obj,
1246         void* eventInfo)
1247 {
1248     LogDebug("createWindowCallback");
1249     Assert(data);
1250     ViewLogic* This = static_cast<ViewLogic*>(data);
1251
1252     // First, current webview should be handled by user callback
1253     if (!This->m_cbs->bufferUnset.empty()) {
1254         This->m_cbs->bufferUnset(obj);
1255     }
1256
1257     // this can be set by executable for specific purpose
1258     Evas* canvas = NULL;
1259     if (!This->m_cbs->windowCreateBefore.empty()) {
1260         // 'obj' is parent webview object
1261         This->m_cbs->windowCreateBefore(&canvas, obj);
1262     }
1263     if (!canvas) {
1264         canvas = evas_object_evas_get(This->m_window);
1265     }
1266
1267     // create new ewkview
1268     This->createEwkView(canvas);
1269     Evas_Object* newEwkView = This->m_currentEwkView;
1270
1271     // initialize new ewkview
1272     This->setStartPage();
1273     This->ewkClientInit(newEwkView);
1274     This->prepareEwkView(newEwkView);
1275
1276     // Specific jobs of child, parent webview are handled by each executable
1277     if (!This->m_cbs->windowCreateAfter.empty()) {
1278         // 'obj' is parent webview, 'newEwkView' is child webview
1279         This->m_cbs->windowCreateAfter(obj, newEwkView);
1280     }
1281
1282     // Lastly, new webview should be handled by user callback
1283     if (!This->m_cbs->bufferSet.empty()) {
1284         This->m_cbs->bufferSet(newEwkView);
1285     }
1286     *(static_cast<Evas_Object **>(eventInfo)) = newEwkView;
1287 }
1288
1289 void ViewLogic::closeWindowCallback(
1290         void* data,
1291         Evas_Object* obj,
1292         void* /*eventInfo*/)
1293 {
1294     LogDebug("closeWindowCallback");
1295     ViewLogic* This = static_cast<ViewLogic*>(data);
1296     This->m_closedEwkView = obj;
1297     ecore_idler_add(windowCloseIdlerCallback, This);
1298 }
1299
1300 void ViewLogic::policyNavigationDecideCallback(
1301         void* data,
1302         Evas_Object* /*obj*/,
1303         void* eventInfo)
1304 {
1305     LogDebug("policyNavigationDecideCallback called");
1306     Assert(data);
1307     ViewLogic* This = static_cast<ViewLogic*>(data);
1308     Assert(eventInfo);
1309     Ewk_Policy_Decision* policyDecision =
1310         static_cast<Ewk_Policy_Decision*>(eventInfo);
1311
1312     if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1313                                                  false,
1314                                                  This->m_model,
1315                                                  This->m_window,
1316                                                  This->m_currentEwkView))
1317     {
1318         LogDebug("use");
1319         ewk_policy_decision_use(policyDecision);
1320     } else {
1321         // check whether this is new empty window
1322         const char* activeUrl = ewk_view_url_get(This->m_currentEwkView);
1323         if(!activeUrl || 0 == strlen(activeUrl)) {
1324             /*
1325              * The view is empty and scheme has been handled externally. When
1326              * user gets back from the external application he'd see blank page
1327              * and won't be able to navigate back. This happens when window.open
1328              * is used to handle schemes like sms/mms/mailto (for example in
1329              * WAC web standards tests: WS-15XX).
1330              *
1331              * To solve the problem, the empty view is removed from the stack
1332              * and the previous one is shown. This is not an elegant solution
1333              * but we don't have a better one.
1334              */
1335             LogInfo("Scheme has been handled externally. Removing empty view.");
1336             if (ewk_view_back_possible(This->m_currentEwkView)) {
1337                 // go back to previous WKPage
1338                 ewk_view_back(This->m_currentEwkView);
1339             } else {
1340                 // stop current WKPage
1341                 ewk_view_stop(This->m_currentEwkView);
1342                 ecore_idler_add(windowCloseIdlerCallback, This);
1343             }
1344         }
1345
1346         LogDebug("ignore");
1347         ewk_policy_decision_ignore(policyDecision);
1348     }
1349 }
1350
1351 void ViewLogic::policyNewWindowDecideCallback(
1352         void* data,
1353         Evas_Object* /*obj*/,
1354         void* eventInfo)
1355 {
1356     LogDebug("policyNewWindowDecideCallback called");
1357     Assert(data);
1358     ViewLogic* This = static_cast<ViewLogic*>(data);
1359     Assert(eventInfo);
1360     Ewk_Policy_Decision* policyDecision =
1361         static_cast<Ewk_Policy_Decision*>(eventInfo);
1362
1363     if (This->m_schemeSupport->filterURIByScheme(policyDecision,
1364                                                  true,
1365                                                  This->m_model,
1366                                                  This->m_window,
1367                                                  This->m_currentEwkView))
1368     {
1369         ewk_policy_decision_use(policyDecision);
1370     } else {
1371         // scheme handled
1372         ewk_policy_decision_ignore(policyDecision);
1373     }
1374 }
1375
1376 void ViewLogic::pageResponseDecideCallback(
1377         void* data,
1378         Evas_Object* /*obj*/,
1379         void* eventInfo)
1380 {
1381     LogDebug("pageResponseDecideCallback called");
1382     Assert(data);
1383     ViewLogic* This = static_cast<ViewLogic*>(data);
1384     Assert(eventInfo);
1385     Ewk_Policy_Decision* policyDecision =
1386         static_cast<Ewk_Policy_Decision*>(eventInfo);
1387     Ewk_Policy_Decision_Type policyDecisionType =
1388         ewk_policy_decision_type_get(policyDecision);
1389
1390     if (policyDecisionType == EWK_POLICY_DECISION_USE) {
1391         LogDebug("use");
1392         ewk_policy_decision_use(policyDecision);
1393     } else if (policyDecisionType == EWK_POLICY_DECISION_DOWNLOAD) {
1394         LogDebug("download");
1395         ewk_policy_decision_suspend(policyDecision);
1396
1397         // get uri information
1398         const char* url =  ewk_policy_decision_url_get(policyDecision);
1399         if (NULL == url || strlen(url) == 0) {
1400             LogDebug("url data is empty");
1401             ewk_policy_decision_use(policyDecision);
1402             return;
1403         }
1404         LogDebug("url = [" << url << "]");
1405
1406         // get content information
1407         const char* content =
1408             ewk_policy_decision_response_mime_get(policyDecision);
1409         LogDebug("content type = [" << content << "]");
1410
1411         // get cookie information
1412         const char* cookie = ewk_policy_decision_cookie_get(policyDecision);
1413         LogDebug("cookie = [" << cookie << "]");
1414
1415         LogDebug("Content not supported, will be opened in external app");
1416         This->m_appsSupport->downloadRequest(
1417             url,
1418             content,
1419             cookie);
1420         ewk_policy_decision_ignore(policyDecision);
1421     } else if (policyDecisionType == EWK_POLICY_DECISION_IGNORE) {
1422         LogDebug("ignore");
1423         ewk_policy_decision_ignore(policyDecision);
1424     } else {
1425         LogDebug("Type isn't handled");
1426         ewk_policy_decision_ignore(policyDecision);
1427     }
1428 }
1429
1430 void ViewLogic::contextmenuCustomizeCallback(
1431         void* data,
1432         Evas_Object* /*obj*/,
1433         void* eventInfo)
1434 {
1435     LogDebug("contextmenuCustomizeCallback called");
1436     Assert(data);
1437     Assert(eventInfo);
1438     ViewLogic* This = static_cast<ViewLogic*>(const_cast<void*>(data));
1439     Ewk_Context_Menu* menu = static_cast<Ewk_Context_Menu*>(eventInfo);
1440     if ((This->m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) &&
1441         (This->m_model->SettingList.Get().getContextMenu()
1442             == ContextMenu_Disable))
1443     {
1444         LogDebug("ContextMenu Disable!!");
1445         for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1446             Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1447             Assert(item);
1448             ewk_context_menu_item_remove(menu, item);
1449         }
1450     } else {
1451         LogDebug("ContextMenu Enable!!");
1452         for (unsigned int idx = 0; idx < ewk_context_menu_item_count(menu);) {
1453             Ewk_Context_Menu_Item* item = ewk_context_menu_nth_item_get(menu, idx);
1454             Assert(item);
1455             Ewk_Context_Menu_Item_Tag tag = ewk_context_menu_item_tag_get(item);
1456
1457             switch (tag) {
1458                 case EWK_CONTEXT_MENU_ITEM_TAG_OPEN_IMAGE_IN_NEW_WINDOW:
1459                     ewk_context_menu_item_remove(menu, item);
1460                     break;
1461
1462                 case EWK_CONTEXT_MENU_ITEM_TAG_SEARCH_WEB:
1463                     ewk_context_menu_item_remove(menu, item);
1464                     break;
1465
1466                 default:
1467                     idx++;
1468                     break;
1469             }
1470         }
1471     }
1472 }
1473
1474 void ViewLogic::formSubmitCallback(
1475         void* /*data*/,
1476         Evas_Object* /*obj*/,
1477         void* eventInfo)
1478 {
1479     LogDebug("formSubmitCallback called");
1480     Assert(eventInfo);
1481     Ewk_Form_Data* formData = static_cast<Ewk_Form_Data*>(eventInfo);
1482
1483     const char* uri = ewk_form_data_url_get(formData);
1484     if (!uri) {
1485         LogError("URL is empty");
1486         return;
1487     }
1488
1489     Eina_Hash* userData = ewk_form_data_values_get(formData);
1490     ViewModule::PasswordSupport::submitClicked(uri, userData);
1491 }
1492
1493 void ViewLogic::geolocationPermissionRequestCallback(
1494         void* data,
1495         Evas_Object* /*obj*/,
1496         void* eventInfo)
1497 {
1498     Assert(data);
1499     ViewLogic* This = static_cast<ViewLogic*>(data);
1500     Assert(eventInfo);
1501     Ewk_Geolocation_Permission_Data* permissionRequest =
1502          static_cast<Ewk_Geolocation_Permission_Data*>(eventInfo);
1503
1504     if (This->m_securityOriginSupport->isNeedPermissionCheck(
1505         SecurityOriginDB::FEATURE_GEOLOCATION)
1506         == WrtDB::SETTINGS_TYPE_OFF)
1507     {
1508         ewk_geolocation_permission_request_allow_set(
1509             ewk_geolocation_permission_request_get(permissionRequest),
1510             EINA_FALSE);
1511         return;
1512     }
1513     ViewModule::GeolocationSupport::Webkit2::geolocationPermissionRequest(
1514         This->m_window,
1515         This->m_securityOriginSupport->getSecurityOriginDAO(),
1516         eventInfo);
1517 }
1518
1519 void ViewLogic::notificationShowCallback(
1520         void* data,
1521         Evas_Object* /*obj*/,
1522         void* eventInfo)
1523 {
1524     LogDebug("notificationShowCallback called");
1525     Assert(data);
1526     ViewLogic* This = static_cast<ViewLogic*>(data);
1527
1528     Assert(eventInfo);
1529     Ewk_Notification* noti = static_cast<Ewk_Notification*>(eventInfo);
1530
1531     using namespace ViewModule::WebNotification;
1532
1533     WebNotificationDataPtr notiData(
1534             new WebNotificationData(
1535                 This->m_model,
1536                 ewk_notification_id_get(noti)));
1537
1538     DPL::OptionalString string =
1539         DPL::FromUTF8String(ewk_notification_icon_url_get(noti));
1540     if (!string.IsNull()) {
1541         notiData->m_iconURL = DPL::ToUTF8String(*string);
1542     }
1543     string = DPL::FromUTF8String(ewk_notification_title_get(noti));
1544     if (!string.IsNull()) {
1545         notiData->m_title = DPL::ToUTF8String(*string);
1546     }
1547     string = DPL::FromUTF8String(ewk_notification_body_get(noti));
1548     if (!string.IsNull()) {
1549         notiData->m_body = DPL::ToUTF8String(*string);
1550     }
1551
1552     LogInfo("notification id : " << notiData->m_id);
1553     LogInfo("notification iconURL : " << notiData->m_iconURL);
1554     LogInfo("notification title : " << notiData->m_title);
1555     LogInfo("notification body : " << notiData->m_body);
1556
1557     showWebNotification(notiData);
1558     ewk_notification_showed(This->m_ewkContext, ewk_notification_id_get(noti));
1559 }
1560
1561 void ViewLogic::notificationCancelCallback(
1562         void* /*data*/,
1563         Evas_Object* /*obj*/,
1564         void* /*eventInfo*/)
1565 {
1566     LogDebug("notificationCancelCallback called");
1567 }
1568
1569 void ViewLogic::notificationPermissionRequestCallback(
1570         void* data,
1571         Evas_Object* /*obj*/,
1572         void* eventInfo)
1573 {
1574     LogDebug("notificationPermissionRequestCallback called");
1575     Assert(data);
1576     ViewLogic* This = static_cast<ViewLogic*>(data);
1577     if (This->m_securityOriginSupport->isNeedPermissionCheck(
1578         SecurityOriginDB::FEATURE_WEB_NOTIFICATION)
1579         == WrtDB::SETTINGS_TYPE_OFF)
1580     {
1581         Ewk_Notification_Permission_Request* request =
1582             static_cast<Ewk_Notification_Permission_Request*>(eventInfo);
1583         ewk_notification_permission_request_response(
1584             This->m_ewkContext,
1585             request,
1586             EINA_FALSE);
1587         return;
1588     }
1589
1590     Assert(eventInfo);
1591     ViewModule::WebNotification::webNotificationPermissionRequest(
1592         This->m_window,
1593         This->m_securityOriginSupport->getSecurityOriginDAO(),
1594         This->m_ewkContext,
1595         eventInfo);
1596     return;
1597 }
1598
1599 void ViewLogic::vibrationVibrateCallback(
1600         void* data,
1601         Evas_Object* /*obj*/,
1602         void* eventInfo)
1603 {
1604     LogDebug("vibrationVibrateCallback called");
1605     Assert(data);
1606     ViewLogic* This = static_cast<ViewLogic*>(data);
1607
1608     Assert(eventInfo);
1609     const long vibrationTime = *(static_cast<const long*>(eventInfo));
1610
1611     // temp
1612     // This->m_vibrationSupport->startVibration(vibrationTime);
1613
1614     return;
1615 }
1616
1617 void ViewLogic::vibrationCancelCallback(
1618         void* data,
1619         Evas_Object* /*obj*/,
1620         void* /*eventInfo*/)
1621 {
1622     LogDebug("vibrationCancelCallback called");
1623     Assert(data);
1624     ViewLogic* This = static_cast<ViewLogic*>(data);
1625
1626     // temp
1627     // This->m_vibrationSupport->stopVibration();
1628
1629     return;
1630 }
1631
1632 // EWK Orientation Callback
1633 Eina_Bool ViewLogic::orientationLockCallback(
1634         Evas_Object* obj,
1635         Eina_Bool /*needLock*/,
1636         int orientation,
1637         void* data)
1638 {
1639     LogDebug("orientationLockCallback called");
1640     Assert(data);
1641     ViewLogic* This = static_cast<ViewLogic*>(data);
1642
1643     if (orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_PRIMARY) {
1644         LogDebug("orientation is portrait-primary");
1645         elm_win_rotation_with_resize_set(This->m_window, 0);
1646         ewk_view_orientation_send(obj, 0);
1647     } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_PRIMARY) {
1648         LogDebug("orientation is landscape-primary");
1649         elm_win_rotation_with_resize_set(This->m_window, 270);
1650         ewk_view_orientation_send(obj, 90);
1651     } else if(orientation & EWK_SCREEN_ORIENTATION_PORTRAIT_SECONDARY) {
1652         LogDebug("orientation is portrait-secondary");
1653         elm_win_rotation_with_resize_set(This->m_window, 180);
1654         ewk_view_orientation_send(obj, 180);
1655     } else if(orientation & EWK_SCREEN_ORIENTATION_LANDSCAPE_SECONDARY) {
1656         LogDebug("orientation is landscape-secondary");
1657         elm_win_rotation_with_resize_set(This->m_window, 90);
1658         ewk_view_orientation_send(obj, -90);
1659     } else {
1660         LogDebug("Wrong orientation is set");
1661         return EINA_FALSE;
1662     }
1663     return EINA_TRUE;
1664 }
1665
1666
1667 // Fullscreen API callbacks
1668 void ViewLogic::enterFullscreenCallback(
1669         void* data,
1670         Evas_Object* /*obj*/,
1671         void* /*eventInfo*/)
1672 {
1673     LogInfo("enterFullscreenCallback called");
1674     Assert(data);
1675     ViewLogic* This = static_cast<ViewLogic*>(data);
1676     if (!This->m_cbs->toggleFullscreen.empty()) {
1677         This->m_cbs->toggleFullscreen(true);
1678     }
1679 }
1680 void ViewLogic::exitFullscreenCallback(
1681         void* data,
1682         Evas_Object* /*obj*/,
1683         void* /*eventInfo*/)
1684 {
1685     LogInfo("exitFullscreenCallback called");
1686     Assert(data);
1687     ViewLogic* This = static_cast<ViewLogic*>(data);
1688     if (!This->m_cbs->toggleFullscreen.empty()) {
1689         This->m_cbs->toggleFullscreen(false);
1690     }
1691 }
1692
1693 void ViewLogic::imeChangedCallback(
1694         void* data,
1695         Evas_Object* /*obj*/,
1696         void* eventInfo)
1697 {
1698     LogDebug("enter");
1699     Assert(data);
1700     Assert(eventInfo);
1701     ViewLogic* This = static_cast<ViewLogic*>(data);
1702     Eina_Rectangle *rect = static_cast<Eina_Rectangle *>(eventInfo);
1703     This->m_imeWidth = rect->w;
1704     This->m_imeHeight = rect->h;
1705 }
1706
1707 void ViewLogic::imeOpenedCallback(
1708         void* data,
1709         Evas_Object* /*obj*/,
1710         void* /*eventInfo*/)
1711 {
1712     LogDebug("enter");
1713     Assert(data);
1714     ViewLogic* This = static_cast<ViewLogic*>(data);
1715
1716     using namespace WrtPlugins::W3C;
1717     SoftKeyboardChangeArgs args;
1718     args.state = IME_STATE_ON;
1719     args.width = This->m_imeWidth;
1720     args.height = This->m_imeHeight;
1721     This->fireJavascriptEvent(
1722             static_cast<int>(SoftKeyboardChangeCustomEvent),
1723             &args);
1724 }
1725
1726 void ViewLogic::imeClosedCallback(
1727         void* data,
1728         Evas_Object* /*obj*/,
1729         void* /*eventInfo*/)
1730 {
1731     LogDebug("enter");
1732     Assert(data);
1733     ViewLogic* This = static_cast<ViewLogic*>(data);
1734
1735     using namespace WrtPlugins::W3C;
1736     SoftKeyboardChangeArgs args;
1737     args.state = IME_STATE_OFF;
1738
1739     This->fireJavascriptEvent(
1740             static_cast<int>(SoftKeyboardChangeCustomEvent),
1741             &args);
1742 }
1743
1744 void ViewLogic::usermediaPermissionRequestCallback(
1745         void* data,
1746         Evas_Object* /*obj*/,
1747         void* eventInfo)
1748 {
1749     LogDebug("usermediaPermissionRequestCallback called");
1750     Assert(data);
1751     ViewLogic* This = static_cast<ViewLogic*>(data);
1752     ViewModule::UsermediaSupport::usermediaPermissionRequest(This->m_window,
1753                                                              eventInfo);
1754 }
1755
1756
1757 // helper method
1758 CustomHandlerDB::CustomHandlerPtr getCustomHandlerFromData(void* data)
1759 {
1760     Assert(data);
1761     Ewk_Custom_Handlers_Data* handler =
1762                 static_cast<Ewk_Custom_Handlers_Data*>(data);
1763     CustomHandlerDB::CustomHandlerPtr customHandler(new CustomHandlerDB::CustomHandler());
1764     const char* base_url = ewk_custom_handlers_data_base_url_get(handler);
1765     if (base_url) {
1766         LogDebug("base url: " << base_url);
1767         customHandler->base_url = DPL::FromASCIIString(string(base_url));
1768     }
1769     const char* url = ewk_custom_handlers_data_url_get(handler);
1770     if (url) {
1771         LogDebug("url: " << url);
1772         customHandler->url = DPL::FromASCIIString(string(url));
1773     }
1774     const char* target = ewk_custom_handlers_data_target_get(handler);
1775     if (target) {
1776         LogDebug("target: " << target);
1777         customHandler->target = DPL::FromASCIIString(string(target));
1778     }
1779     const char* title = ewk_custom_handlers_data_title_get(handler);
1780     if (title) {
1781         LogDebug("title: " << title);
1782         customHandler->title = DPL::FromASCIIString(string(title));
1783     }
1784     return customHandler;
1785 }
1786
1787 void ViewLogic::attachToCustomHandlersDao()
1788 {
1789     if (!m_attachedToCustomHandlerDao) {
1790         CustomHandlerDB::Interface::attachDatabaseRW();
1791     }
1792 }
1793
1794 void ViewLogic::detachFromCustomHandlersDao()
1795 {
1796     if (m_attachedToCustomHandlerDao) {
1797         CustomHandlerDB::Interface::detachDatabase();
1798     }
1799 }
1800
1801 const int protocolWhiteListLenth = 15;
1802 char const * const protocolWhiteList[protocolWhiteListLenth] = {
1803     "irc",
1804     "geo",
1805     "mailto",
1806     "magnet",
1807     "mms",
1808     "news",
1809     "nntp",
1810     "sip",
1811     "sms",
1812     "smsto",
1813     "ssh",
1814     "tel",
1815     "urn",
1816     "webcal",
1817     "xmpp"
1818 };
1819
1820 const int contentBlackListLenth = 14;
1821 char const * const contentBlackList[contentBlackListLenth] = {
1822     "application/x-www-form-urlencoded",
1823     "application/xhtml+xml",
1824     "application/xml",
1825     "image/gif",
1826     "image/jpeg",
1827     "image/png",
1828     "image/svg+xml",
1829     "multipart/x-mixed-replace",
1830     "text/cache-manifest",
1831     "text/css",
1832     "text/html",
1833     "text/ping",
1834     "text/plain",
1835     "text/xml"
1836 };
1837
1838 /**
1839  * Saves user's response from popup to custom handler. Saves Yes/No and remember
1840  * state.
1841  * @param response
1842  * @param customHandler
1843  */
1844 void saveUserResponse(Wrt::Popup::PopupResponse response,
1845         CustomHandlerDB::CustomHandlerPtr customHandler)
1846 {
1847     switch (response) {
1848         case Wrt::Popup::YES_DO_REMEMBER:
1849             LogDebug("User allowed, remember");
1850             customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1851                 (CustomHandlerDB::Agreed | CustomHandlerDB::DecisionSaved);
1852             break;
1853         case Wrt::Popup::YES_DONT_REMEMBER:
1854             LogDebug("User allowed, don't remember");
1855             customHandler->user_decision = CustomHandlerDB::Agreed;
1856             break;
1857         case Wrt::Popup::NO_DO_REMEMBER:
1858             LogDebug("User didn't allow, remember");
1859             customHandler->user_decision = static_cast<CustomHandlerDB::HandlerState>
1860                     (CustomHandlerDB::Declined | CustomHandlerDB::DecisionSaved);
1861             break;
1862         case Wrt::Popup::NO_DONT_REMEMBER:
1863             LogDebug("User didn't allow, don't remember");
1864             customHandler->user_decision = CustomHandlerDB::Declined;
1865             break;
1866     }
1867 }
1868
1869 //TODO registration, checking if registered and unregistration can be done in
1870 //common functions for both types of handlers. Only white and black lists
1871 //have to be separated
1872 //TODO attach database only one at the start (not in every callback?)
1873 void ViewLogic::protocolHandlerRegistrationCallback(void* data,
1874                                                     Evas_Object* obj,
1875                                                     void* eventInfo)
1876 {
1877     Assert(data);
1878     LogDebug("enter");
1879     CustomHandlerDB::CustomHandlerPtr customHandler =
1880             getCustomHandlerFromData(eventInfo);
1881
1882     std::string scheme = DPL::ToUTF8String(customHandler->target);
1883     if (scheme.empty()) {
1884         LogError("No scheme provided");
1885         //TODO what about securityError?
1886         return;
1887     }
1888     bool matched = false;
1889     //scheme on whiteList
1890     for (int i = 0; i < protocolWhiteListLenth; ++i) {
1891         if (0 == strcmp(protocolWhiteList[i], scheme.c_str()))
1892         {
1893             LogDebug("Match found, protocol can be handled");
1894             matched = true;
1895         }
1896     }
1897     if (!matched) {
1898         //starts with web+ and have at least 5 chars (lowercase ASCII)
1899         if (strncmp("web+", scheme.c_str(), 4) || scheme.length() < 5) {
1900             LogWarning("Scheme neither on whitelist nor starts with \"web+\"");
1901             //throw SecurityException
1902             return;
1903         }
1904         int l = 4;
1905         char c = scheme[l];
1906         while (c != '\0')
1907         {
1908             if (c < 'a' || c > 'z') {
1909                 LogWarning("Wrong char inside scheme. "
1910                            << "Only lowercase ASCII letters accepted");
1911                 //throw SecurityException
1912                 return;
1913             }
1914             c = scheme[++l];
1915         }
1916     }
1917
1918     ViewLogic* This = static_cast<ViewLogic*>(data);
1919     LogDebug("Creating handlers dao");
1920     This->attachToCustomHandlersDao();
1921     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1922     CustomHandlerDB::CustomHandlerPtr handler =
1923             handlersDao.getProtocolHandler(customHandler->target,
1924                                            customHandler->url,
1925                                            customHandler->base_url);
1926     if (handler && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
1927         LogDebug("Protocol already registered - nothing to do");
1928     } else {
1929         LogDebug("Protocol handler not found");
1930         Wrt::Popup::PopupResponse response =
1931             GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
1932                 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
1933                         PROTOCOL_HANDLER_ASK_TITLE,
1934                         PROTOCOL_HANDLER_ASK_MSG,
1935                         PROTOCOL_HANDLER_ASK_REMEMBER);
1936         saveUserResponse(response, customHandler);
1937         if (customHandler->user_decision == CustomHandlerDB::Declined)
1938             return;
1939         handlersDao.registerProtocolHandler(*(customHandler.get()));
1940         if (customHandler->user_decision & CustomHandlerDB::Agreed) {
1941             //TODO remove old default handler somehow from appsvc
1942             LogDebug("Registering appservice entry");
1943             int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
1944                     NULL,
1945                     DPL::ToUTF8String(customHandler->target).c_str(),
1946                     DPL::ToUTF8String(This->m_model->TizenId).c_str());
1947             if (APPSVC_RET_OK != ret)
1948             {
1949                 LogWarning("Appsvc entry failed: " << ret);
1950             }
1951         }
1952         LogDebug("Protocal saved");
1953     }
1954
1955     This->detachFromCustomHandlersDao();
1956 }
1957
1958 void ViewLogic::protocolHandlerIsRegisteredCallback(void* data,
1959                                                     Evas_Object* obj,
1960                                                     void* eventInfo)
1961 {
1962     LogDebug("enter");
1963     CustomHandlerDB::CustomHandlerPtr customHandler = getCustomHandlerFromData(eventInfo);
1964     ViewLogic* This = static_cast<ViewLogic*>(data);
1965     LogDebug("Creating handlers dao");
1966     This->attachToCustomHandlersDao();
1967     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1968         CustomHandlerDB::CustomHandlerPtr handler =
1969             handlersDao.getProtocolHandler(customHandler->target,
1970                                            customHandler->url,
1971                                            customHandler->base_url);
1972     if (handler) {
1973         if (handler->user_decision & CustomHandlerDB::Agreed)
1974             ewk_custom_handlers_data_result_set(
1975                 static_cast<Ewk_Custom_Handlers_Data*>(data),
1976                 EWK_CUSTOM_HANDLERS_REGISTERED);
1977         else
1978             ewk_custom_handlers_data_result_set(
1979                 static_cast<Ewk_Custom_Handlers_Data*>(data),
1980                 EWK_CUSTOM_HANDLERS_DECLINED);
1981     } else
1982             ewk_custom_handlers_data_result_set(
1983                 static_cast<Ewk_Custom_Handlers_Data*>(data),
1984                 EWK_CUSTOM_HANDLERS_NEW);
1985     This->detachFromCustomHandlersDao();
1986 }
1987
1988 void ViewLogic::protocolHandlerUnregistrationCallback(void* data,
1989                                                       Evas_Object* obj,
1990                                                       void* eventInfo)
1991 {
1992     LogDebug("enter");
1993     CustomHandlerDB::CustomHandlerPtr customHandler =
1994             getCustomHandlerFromData(eventInfo);
1995     ViewLogic* This = static_cast<ViewLogic*>(data);
1996     LogDebug("Creating handlers dao");
1997     This->attachToCustomHandlersDao();
1998     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
1999     CustomHandlerDB::CustomHandlerPtr handlerCheck =
2000         handlersDao.getProtocolHandler(customHandler->target,
2001                                        customHandler->url,
2002                                        customHandler->base_url);
2003     if (handlerCheck) {
2004         if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2005             appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2006
2007         handlersDao.unregisterProtocolHandler(customHandler->target,
2008                                               customHandler->url,
2009                                               customHandler->base_url);
2010     } else
2011         LogDebug("Nothing to unregister");
2012
2013     This->detachFromCustomHandlersDao();
2014 }
2015
2016 void ViewLogic::contentHandlerRegistrationCallback(void* data,
2017                                                    Evas_Object* obj,
2018                                                    void* eventInfo)
2019 {
2020     Assert(data);
2021     LogDebug("enter");
2022     CustomHandlerDB::CustomHandlerPtr customHandler =
2023             getCustomHandlerFromData(eventInfo);
2024
2025     std::string mimeType = DPL::ToUTF8String(customHandler->target);
2026     if (mimeType.empty()) {
2027         LogError("No mimeType provided.");
2028         return;
2029     }
2030     for (int i = 0; i < contentBlackListLenth; ++i)
2031     {
2032         if (0 == strcmp(contentBlackList[i], mimeType.c_str()))
2033         {
2034             LogWarning("mimeType blacklisted");
2035             //throw SecurityException
2036             return;
2037         }
2038     }
2039
2040     ViewLogic* This = static_cast<ViewLogic*>(data);
2041     LogDebug("Creating handlers dao");
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 && (handler->user_decision & CustomHandlerDB::DecisionSaved)) {
2049         LogDebug("Protocol already registered - nothing to do");
2050     } else {
2051         LogDebug("Protocol handler not found");
2052         Wrt::Popup::PopupResponse response =
2053             GlobalSettings::PopupsTestModeEnabled() ? Wrt::Popup::YES_DO_REMEMBER :
2054                 Wrt::Popup::PopupInvoker().askYesNoCheckbox(
2055                         CONTENT_HANDLER_ASK_TITLE,
2056                         CONTENT_HANDLER_ASK_MSG,
2057                         CONTENT_HANDLER_AKS_REMEMBER);
2058         saveUserResponse(response, customHandler);
2059         if (customHandler->user_decision == CustomHandlerDB::Declined)
2060             return;
2061         handlersDao.registerContentHandler(*(customHandler.get()));
2062         if (customHandler->user_decision & CustomHandlerDB::Agreed) {
2063             //TODO remove old default handler somehow from appsvc
2064             LogDebug("Registering appservice entry");
2065             int ret = appsvc_set_defapp(APPSVC_OPERATION_VIEW,
2066                     DPL::ToUTF8String(customHandler->target).c_str(),
2067                     NULL,
2068                     DPL::ToUTF8String(This->m_model->TizenId).c_str());
2069             if (APPSVC_RET_OK != ret)
2070             {
2071                 LogWarning("Appsvc entry failed: " << ret);
2072             }
2073         }
2074         LogDebug("Content saved");
2075     }
2076     This->detachFromCustomHandlersDao();
2077 }
2078
2079 void ViewLogic::contentHandlerIsRegisteredCallback(void* data,
2080                                                    Evas_Object* obj,
2081                                                    void* eventInfo)
2082 {
2083     LogDebug("enter");
2084     CustomHandlerDB::CustomHandlerPtr customHandler =
2085         getCustomHandlerFromData(eventInfo);
2086     ViewLogic* This = static_cast<ViewLogic*>(data);
2087     LogDebug("Creating handlers dao");
2088
2089     This->attachToCustomHandlersDao();
2090     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2091         CustomHandlerDB::CustomHandlerPtr handler =
2092             handlersDao.getContentHandler(customHandler->target,
2093                                           customHandler->url,
2094                                           customHandler->base_url);
2095     if (handler) {
2096         if (handler->user_decision & CustomHandlerDB::Agreed)
2097             ewk_custom_handlers_data_result_set(
2098                 static_cast<Ewk_Custom_Handlers_Data*>(data),
2099                 EWK_CUSTOM_HANDLERS_REGISTERED);
2100         else
2101             ewk_custom_handlers_data_result_set(
2102                 static_cast<Ewk_Custom_Handlers_Data*>(data),
2103                 EWK_CUSTOM_HANDLERS_DECLINED);
2104     } else
2105             ewk_custom_handlers_data_result_set(
2106                 static_cast<Ewk_Custom_Handlers_Data*>(data),
2107                 EWK_CUSTOM_HANDLERS_NEW);
2108     This->detachFromCustomHandlersDao();
2109 }
2110
2111 void ViewLogic::contentHandlerUnregistrationCallback(void* data,
2112                                                      Evas_Object* obj,
2113                                                      void* eventInfo)
2114 {
2115     LogDebug("enter");
2116     CustomHandlerDB::CustomHandlerPtr customHandler =
2117             getCustomHandlerFromData(eventInfo);
2118     ViewLogic* This = static_cast<ViewLogic*>(data);
2119     LogDebug("Creating handlers dao");
2120     This->attachToCustomHandlersDao();
2121     CustomHandlerDB::CustomHandlerDAO handlersDao(This->m_model->TizenId);
2122         CustomHandlerDB::CustomHandlerPtr handlerCheck =
2123             handlersDao.getContentHandler(customHandler->target,
2124                                            customHandler->url,
2125                                            customHandler->base_url);
2126         if (handlerCheck) {
2127             if (handlerCheck->user_decision & CustomHandlerDB::Agreed)
2128                 appsvc_unset_defapp(DPL::ToUTF8String(This->m_model->TizenId).c_str());
2129
2130             handlersDao.unregisterContentHandler(customHandler->target,
2131                                                      customHandler->url,
2132                                                      customHandler->base_url);
2133         } else
2134             LogDebug("Nothing to unregister");
2135     This->detachFromCustomHandlersDao();
2136 }
2137
2138 void ViewLogic::didRunJavaScriptCallback(
2139         Evas_Object* /*obj*/,
2140         const char* result,
2141         void* /*userData*/)
2142 {
2143     LogInfo("didRunJavaScriptCallback called");
2144     LogInfo("result = " << result);
2145 }
2146
2147 Eina_Bool ViewLogic::windowCloseIdlerCallback(void* data)
2148 {
2149     LogDebug("closeIdlerCallback");
2150     ViewLogic* This = static_cast<ViewLogic*>(data);
2151     This->windowClose();
2152     return ECORE_CALLBACK_CANCEL;
2153 }
2154
2155 int ViewLogic::appcoreLowMemoryCallback(void *data)
2156 {
2157     LogInfo("appcoreLowMemoryCallback");
2158     Assert(data);
2159     ViewLogic* This = static_cast<ViewLogic*>(data);
2160
2161     if (NULL == This->m_ewkContext) {
2162         LogInfo("ewk isn't initialize at this moment");
2163     } else {
2164         // Crash may occur on specific situation
2165         // So use the followings after they become stable
2166         //ewk_context_cache_clear(This->m_ewkContext);
2167         //ewk_context_notify_low_memory(This->m_ewkContext);
2168     }
2169
2170     return 0;
2171 }
2172
2173 void ViewLogic::databaseUsagePermissionRequestCallback(
2174     void* data,
2175     Evas_Object* /*obj*/,
2176     void* eventInfo)
2177 {
2178     LogDebug("databaseUsagePermissionRequestCallback called");
2179     Assert(data);
2180     ViewLogic* This = static_cast<ViewLogic*>(data);
2181     Assert(eventInfo);
2182
2183     if (This->m_securityOriginSupport->isNeedPermissionCheck(
2184         SecurityOriginDB::FEATURE_WEB_DATABASE)
2185         == WrtDB::SETTINGS_TYPE_OFF)
2186     {
2187         // default value is deny
2188         return;
2189     }
2190     ViewModule::WebStorageSupport::webStorageCreatePermissionRequest(
2191         This->m_window,
2192         This->m_securityOriginSupport->getSecurityOriginDAO(),
2193         eventInfo);
2194     return;
2195  }
2196
2197 void ViewLogic::fileSystemPermissionRequestCallback(
2198     void* data,
2199     Evas_Object* /*obj*/,
2200     void* eventInfo)
2201 {
2202     LogDebug("fileSystemPermissionRequestCallback called");
2203     Assert(data);
2204     ViewLogic* This = static_cast<ViewLogic*>(data);
2205
2206     if (This->m_securityOriginSupport->isNeedPermissionCheck(
2207         SecurityOriginDB::FEATURE_FILE_SYSTEM_ACCESS)
2208         == WrtDB::SETTINGS_TYPE_OFF)
2209     {
2210         Ewk_Context_File_System_Permission* fileSystemPermission =
2211              static_cast<Ewk_Context_File_System_Permission*>(eventInfo);
2212         ewk_context_file_system_permission_allow_set(fileSystemPermission,
2213                                                      EINA_FALSE);
2214         return;
2215     }
2216
2217     Assert(eventInfo);
2218     ViewModule::FileSystemSupport::fileSystemPermissionRequest(
2219         This->m_window,
2220         This->m_securityOriginSupport->getSecurityOriginDAO(),
2221         eventInfo);
2222 }
2223
2224 void ViewLogic::didRecieveMessageFromInjectedBundle(
2225         const char* name,
2226         const char* /*body*/)
2227 {
2228     LogDebug("did recive message " << name);
2229 }
2230
2231 void ViewLogic::didReceiveSynchronousMessage(
2232         const char* name,
2233         const char* body,
2234         char** returnData)
2235 {
2236     LogDebug("didReceiveSynchronousMessage called");
2237     Assert(name);
2238     Assert(returnData);
2239
2240     if (!body) {
2241         LogDebug("body is empty");
2242         *returnData = NULL;
2243         return;
2244     }
2245     if (!strcmp(name, uriBlockedMessageName)) {
2246         LogDebug("received : " << uriBlockedMessageName);
2247         // Currently WebProcess informs obly about blocked
2248         // URI - URI localization and security chekcs are
2249         // done by WebProcess itself (see: wrt-wk2-bundle.cpp
2250         // and bundle_uri_handling.cpp)
2251         rememberBlockedURI(DPL::FromUTF8String(body));
2252         *returnData = NULL;
2253     } else if (!strcmp(name, uriChangedMessageName)) {
2254         LogDebug("received : " << uriChangedMessageName);
2255         std::string ret = requestUriChanged(DPL::FromUTF8String(body));
2256         *returnData =  strdup(ret.c_str());
2257     }
2258 }
2259
2260 void ViewLogic::rememberBlockedURI(const DPL::String& inputURI)
2261 {
2262     m_blockedUri = DPL::ToUTF8String(inputURI);
2263     LogInfo("set blocked uri to open browser later : " << m_blockedUri);
2264     return;
2265 }
2266
2267 std::string ViewLogic::requestUriChanged(const DPL::String& changedURL)
2268 {
2269     using namespace ViewModule::SecuritySupport;
2270
2271     std::string url = DPL::ToUTF8String(changedURL);
2272     LogInfo("URL = [" << url << "]");
2273
2274     // check WARP
2275     // If url is same to URICHANGE_BLOCKED_URL,
2276     // this url has been already blocked by willsend.
2277     // So current page should be moved to previous page
2278     if (url == URICHANGE_BLOCKED_URL)
2279     {
2280         if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP)
2281         {
2282             // block this page and open it in browser
2283             LogDebug("Request was blocked by WARP: " << url.c_str());
2284             if (!m_blockedUri.empty()) {
2285                 LogDebug("open browser : " << m_blockedUri);
2286                 bundle* bundleData = bundle_create();
2287                 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
2288                 appsvc_set_uri(bundleData, m_blockedUri.c_str());
2289                 CONTROLLER_POST_EVENT(
2290                     ApplicationLauncher,
2291                     ApplicationLauncherEvents::LaunchApplicationByAppService(
2292                         bundleData,
2293                         NULL,
2294                         NULL));
2295                 m_blockedUri = std::string();
2296             }
2297         }
2298         if (ewk_view_back_possible(m_currentEwkView)) {
2299             // go back to previous page
2300             ewk_view_back(m_currentEwkView);
2301         } else {
2302             // stop current page
2303             ewk_view_stop(m_currentEwkView);
2304             ecore_idler_add(windowCloseIdlerCallback, this);
2305         }
2306
2307         // This is used in case of returning previous page
2308         m_currentUri = url;
2309         return URICHANGE_PLUGIN_NO_CHANGE;
2310     }
2311
2312     m_currentUri = url;
2313
2314     // Check if this url with 'http' or 'https' is included in whitelist,
2315     // which has lists of accessible external documents and
2316     // used for ONLY Tizen app
2317     std::string matchedScheme;
2318     std::string matchedUri;
2319     pcrecpp::RE(PATTERN_URI_CHANGE).PartialMatch(url.c_str(),
2320                                                  &matchedUri,
2321                                                  &matchedScheme);
2322     ViewModule::Scheme scheme(matchedScheme);
2323     if (scheme.GetType() == ViewModule::Scheme::HTTP ||
2324         scheme.GetType() == ViewModule::Scheme::HTTPS)
2325     {
2326         if (m_model->Type.Get().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
2327             if (!checkWhitelist(url.c_str())) {
2328                 LogInfo("This uri is not included in white document list");
2329                 return URICHANGE_PLUGIN_STOP_ONLY;
2330             }
2331             LogInfo("This url is included in WhiteList");
2332         } else {
2333             // For WAC app, WRT should block access of device api
2334             // for external documents
2335             return URICHANGE_PLUGIN_STOP_ONLY;
2336         }
2337     }
2338
2339     // register javascript object for plugins to be used
2340     LogInfo("Register Plugin Objects");
2341     return URICHANGE_PLUGIN_RESTART;
2342 }
2343
2344 void ViewLogic::windowClose()
2345 {
2346     LogDebug("windowClose");
2347     Assert(m_closedEwkView && "no closed webview");
2348
2349     if (1 >= m_ewkViewList.size()) {
2350         if (!m_cbs->webkitExit.empty()) {
2351             m_cbs->webkitExit();
2352         }
2353     } else {
2354         // call user callbacks
2355         if (!m_cbs->bufferUnset.empty()) {
2356             m_cbs->bufferUnset(m_currentEwkView);
2357         }
2358         if (!m_cbs->windowClose.empty()) {
2359             m_cbs->windowClose(m_closedEwkView);
2360         }
2361         removeEwkView(m_closedEwkView);
2362
2363         // get latest ewkView
2364         m_currentEwkView = m_ewkViewList.back();
2365         const char* uri = ewk_view_url_get(m_currentEwkView);
2366         if (NULL == uri || 0 == strlen(uri)) {
2367             m_currentUri.clear();
2368         } else {
2369             m_currentUri = uri;
2370         }
2371
2372         // resume ewkView
2373         /* In case we support many pages in parallel
2374            then view is not suspended*/
2375         //resumeEwkView(m_currentEwkView);
2376
2377         // show ewkView
2378         if (!m_cbs->bufferSet.empty()) {
2379             m_cbs->bufferSet(m_currentEwkView);
2380         }
2381     }
2382 }
2383