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