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