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