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