For launching time performance, patch to not exec web process.
[platform/framework/web/wrt.git] / src / wrt-client / wrt-client.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 #include "wrt-client.h"
17 #include <cstdlib>
18 #include <cstdio>
19 #include <string>
20 #include <dpl/log/log.h>
21 #include <dpl/optional_typedefs.h>
22 #include <dpl/exception.h>
23 #include <common/application_data.h>
24 #include <core_module.h>
25 #include <localization_setting.h>
26 #include <widget_deserialize_model.h>
27 #include <EWebKit2.h>
28 #include <dpl/localization/w3c_file_localization.h>
29 #include <dpl/localization/LanguageTagsProvider.h>
30
31 //W3C PACKAGING enviroment variable name
32 #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
33
34 // window signal callback
35 const char *EDJE_SHOW_BACKWARD_SIGNAL = "show,backward,signal";
36 const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
37 const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized";
38 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
39 const char* const BUNDLE_PATH = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
40
41 static Ewk_Context* s_ewk_context = NULL;
42
43 WrtClient::WrtClient(int argc, char **argv) :
44     Application(argc, argv, "wrt-client", false),
45     DPL::TaskDecl<WrtClient>(this),
46     m_launched(false),
47     m_initializing(false),
48     m_initialized(false),
49     m_sdkLauncherPid(0),
50     m_debugMode(false),
51     m_debuggerPort(0),
52     m_returnStatus(ReturnStatus::Succeeded),
53     m_widgetState(WidgetState::WidgetState_Stopped)
54 {
55     Touch();
56     LogDebug("App Created");
57 }
58
59 WrtClient::~WrtClient()
60 {
61     LogDebug("App Finished");
62 }
63
64 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
65 {
66     return m_returnStatus;
67 }
68
69 void WrtClient::OnStop()
70 {
71     LogInfo("Stopping Dummy Client");
72 }
73
74
75 void WrtClient::OnCreate()
76 {
77     LogInfo("On Create");
78     ADD_PROFILING_POINT("OnCreate callback", "point");
79     ewk_init();
80 }
81
82
83 void WrtClient::OnResume()
84 {
85     if (m_widgetState != WidgetState_Suspended) {
86         LogWarning("Widget is not suspended, resuming was skipped");
87         return;
88     }
89     m_widget->Resume();
90     m_widgetState = WidgetState_Running;
91 }
92
93
94 void WrtClient::OnPause()
95 {
96     LogDebug("On pause");
97
98     if (m_widgetState != WidgetState_Running) {
99         LogWarning("Widget is not running to be suspended");
100         return;
101     }
102     m_widget->Suspend();
103     m_widgetState = WidgetState_Suspended;
104 }
105
106 void WrtClient::OnReset(bundle *b)
107 {
108     LogDebug("OnReset");
109     // bundle argument is freed after OnReset() is returned
110     // So bundle duplication is needed
111     ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
112
113     if (true == m_initializing) {
114         LogDebug("can not handle reset event");
115         return;
116     }
117     if (true == m_launched) {
118         if (m_widgetState == WidgetState_Stopped) {
119             LogError("Widget is not running to be reset");
120             return;
121         }
122         m_widget->Reset();
123         m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
124         m_widgetState = WidgetState_Running;
125     } else {
126         if (true == checkArgument())
127         {
128             setStep();
129         }
130         else
131         {
132             showHelpAndQuit();
133         }
134     }
135 }
136
137 void WrtClient::OnTerminate()
138 {
139     LogDebug("Wrt Shutdown now");
140     shutdownStep();
141 }
142
143 void WrtClient::showHelpAndQuit()
144 {
145     printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
146            "launch widgets.\n"
147            "Mandatory arguments to long options are mandatory for short "
148            "options too.\n"
149            "  -h,    --help                                 show this help\n"
150            "  -l,    --launch                               "
151            "launch widget with given tizen ID\n"
152            "  -t,    --tizen                                "
153            "launch widget with given tizen ID\n"
154            "\n");
155
156     Quit();
157 }
158
159 bool WrtClient::checkArgument()
160 {
161     std::string tizenId = getTizenIdFromArgument(m_argc, m_argv);
162
163     if(tizenId.empty()){
164         // Just show help
165         return false;
166     } else {
167         m_tizenId = tizenId;
168         LogDebug("Tizen id: " << m_tizenId);
169         return true;
170     }
171 }
172
173 std::string WrtClient::getTizenIdFromArgument(int argc, char **argv)
174 {
175     LogInfo("checkArgument");
176     std::string arg = argv[0];
177
178     if (arg.empty()) {
179         return "";
180     }
181
182     if (arg.find("wrt-client") != std::string::npos) {
183         if (argc <= 1) {
184             return "";
185         }
186
187         arg = argv[1];
188
189         if (arg == "-h" || arg == "--help") {
190             return "";
191         } else if (arg == "-l" || arg == "--launch" ||
192                 arg == "-t" || arg == "--tizen") {
193             if (argc != 3) {
194                 return "";
195             }
196             return argv[2];
197         } else {
198             return "";
199         }
200     } else {
201         // Launch widget based on application basename
202         size_t pos = arg.find_last_of('/');
203
204         if (pos != std::string::npos) {
205             arg = arg.erase(0, pos + 1);
206         }
207
208         return arg;
209     }
210
211     return "";
212 }
213
214 void WrtClient::setStep()
215 {
216     LogInfo("setStep");
217
218     AddStep(&WrtClient::initStep);
219
220     setSdkLauncherDebugData();
221
222     AddStep(&WrtClient::launchStep);
223     AddStep(&WrtClient::shutdownStep);
224
225     m_initializing = true;
226
227     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
228 }
229
230 void WrtClient::setSdkLauncherDebugData()
231 {
232     LogDebug("setSdkLauncherDebugData");
233
234     /* check bundle from sdk launcher */
235     bundle *bundleFromSdkLauncher;
236     bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
237     const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
238     const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
239     if (bundle_debug != NULL && bundle_pid != NULL) {
240         if (strcmp(bundle_debug, "true") == 0) {
241             m_debugMode = true;
242             m_sdkLauncherPid = atoi(bundle_pid);
243         } else {
244             m_debugMode = false;
245         }
246     }
247     bundle_free(bundleFromSdkLauncher);
248 }
249
250 bool WrtClient::checkDebugMode(SDKDebugData* debugData)
251 {
252     LogError("Checking for debug mode");
253     Assert(m_dao);
254
255     bool debugMode = debugData->debugMode;
256
257     LogInfo("[DEBUG_MODE] Widget is launched in " <<
258             (debugMode ? "DEBUG" : "RETAIL") <<
259             " mode.");
260
261     if (debugMode == true) {
262         // In WAC widget, only test widgets can use web inspector.
263         // In TIZEN widget,
264         // every launched widgets as debug mode can use it.
265         if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_WAC20)
266         {
267             bool developerMode = WRT::CoreModuleSingleton::Instance().developerMode();
268             //This code will be activated
269             //after WAC test certificate is used by SDK
270             //bool isTestWidget = view->m_widgetModel->IsTestWidget.Get();
271             //if(!isTestWidget)
272             //{
273             //    LogInfo("This is not WAC Test Widget");
274             //    break;
275             //}
276             if (!developerMode) {
277                 LogInfo("This is not WAC Developer Mode");
278                 debugMode = false;
279             }
280         }
281     }
282     return debugMode;
283 }
284
285 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
286 {
287     LogDebug("Executing next step");
288     NextStep();
289 }
290
291 void WrtClient::initStep()
292 {
293     LogDebug("");
294     if (WRT::CoreModuleSingleton::Instance().Init(s_ewk_context)) {
295         m_initialized = true;
296     } else {
297         m_returnStatus = ReturnStatus::Failed;
298         SwitchToStep(&WrtClient::shutdownStep);
299     }
300
301     // ecore_event_jobs are processed sequentially without concession to
302     // other type events. To give a chance of execute to other events,
303     // ecore_timer_add was used.
304     DPL::Event::ControllerEventHandler<NextStepEvent>::PostTimedEvent(
305             NextStepEvent(),0.001);
306 }
307
308 bool WrtClient::checkWACTestCertififedWidget()
309 {
310     // WAC Waikiki Beta Release Core Specification: Widget Runtime
311     // 10 Dec 2010
312     //
313     // WR-4710 The WRT MUST enable debug functions only for WAC test widgets
314     // i.e. the functions must not be usable for normal WAC widgets, even when
315     // a WAC test widget is executing.
316     ADD_PROFILING_POINT("DeveloperModeCheck", "start");
317     Assert(!!m_dao);
318     // WAC test widget
319     // A widget signed with a WAC-issued test certificate as described in
320     // Developer Mode.
321
322     bool developerWidget = m_dao->isTestWidget();
323     bool developerMode = WRT::CoreModuleSingleton::Instance().developerMode();
324
325     LogDebug("Is WAC test widget: " << developerWidget);
326     LogDebug("Is developer Mode: " << developerMode);
327
328     if (developerWidget) {
329         if(!developerMode)
330         {
331             LogError("WAC test certified developer widget is needed for " <<
332                     "developer mode");
333             return false;
334         }else{
335             //TODO: WR-4660 (show popup about developer widget
336             //      during launch
337             LogInfo("POPUP: THIS IS TEST WIDGET!");
338         }
339     }
340     ADD_PROFILING_POINT("DeveloperModeCheck", "stop");
341     return true;
342 }
343
344 void WrtClient::loadFinishCallback(Evas_Object* webview)
345 {
346     ADD_PROFILING_POINT("loadFinishCallback", "start");
347     SDKDebugData* debug = new SDKDebugData;
348     debug->debugMode = m_debugMode;
349     debug->pid = new unsigned long(getpid());
350
351     LogInfo("Post result of launch");
352
353     // Start inspector server, if current mode is debugger mode.
354     // In the WK2 case, ewk_view_inspector_server_start should
355     // be called after WebProcess is created.
356     if (checkDebugMode(debug))
357     {
358         debug->portnum =
359             ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0);
360         if (debug->portnum == 0) {
361             LogWarning("Failed to get portnum");
362         } else {
363             LogInfo("Assigned port number for inspector : "
364                     << debug->portnum);
365         }
366     } else {
367         LogDebug("Debug mode is disabled");
368     }
369
370     //w3c packaging test debug (message on 4>)
371     const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
372     if(makeScreen != NULL && strcmp(makeScreen, "1") == 0)
373     {
374         FILE* doutput = fdopen(4, "w");
375         fprintf(doutput,"didFinishLoadForFrameCallback: ready\n");
376         fclose(doutput);
377     }
378
379     if (webview) {
380         LogDebug("Launch succesfull");
381
382         m_launched = true;
383         m_initializing = false;
384         setlinebuf(stdout);
385         ADD_PROFILING_POINT("loadFinishCallback", "stop");
386         printf("launched\n");
387         fflush(stdout);
388     } else {
389         printf("failed\n");
390
391         m_returnStatus = ReturnStatus::Failed;
392         //shutdownStep
393         DPL::Event::ControllerEventHandler<NextStepEvent>::
394                 PostEvent(NextStepEvent());
395     }
396
397     if(debug->debugMode)
398     {
399         LogDebug("Send RT signal to wrt-launcher(pid: " << m_sdkLauncherPid);
400         union sigval sv;
401         /* send real time signal with result to wrt-launcher */
402         if(webview) {
403             LogDebug("userData->portnum : " << debug->portnum);
404             sv.sival_int = debug->portnum;
405         } else {
406            sv.sival_int = -1;
407         }
408         sigqueue(m_sdkLauncherPid, SIGRTMIN, sv);
409     }
410
411     ApplicationDataSingleton::Instance().freeBundle();
412
413     LogDebug("Cleaning wrtClient launch resources...");
414     delete debug->pid;
415     delete debug;
416 }
417
418 void WrtClient::progressFinishCallback()
419 {
420     m_splashScreen->stopSplashScreen();
421 }
422
423 void WrtClient::webkitExitCallback()
424 {
425     LogDebug("window close called, terminating app");
426     SwitchToStep(&WrtClient::shutdownStep);
427     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
428             NextStepEvent());
429 }
430
431 void WrtClient::webCrashCallback()
432 {
433     LogError("webProcess crashed");
434     SwitchToStep(&WrtClient::shutdownStep);
435     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
436             NextStepEvent());
437 }
438
439
440 void WrtClient::launchStep()
441 {
442     ADD_PROFILING_POINT("launchStep", "start");
443     LogDebug("Launching widget ...");
444
445     ADD_PROFILING_POINT("getRunnableWidgetObject", "start");
446     m_widget = WRT::CoreModuleSingleton::Instance()
447                     .getRunnableWidgetObject(m_tizenId);
448     ADD_PROFILING_POINT("getRunnableWidgetObject", "stop");
449
450     if (!m_widget) {
451         LogError("RunnableWidgetObject is NULL, stop launchStep");
452         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
453                     NextStepEvent());
454         return;
455     }
456
457     if (m_widgetState == WidgetState_Running) {
458         LogWarning("Widget already running, stop launchStep");
459         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
460                     NextStepEvent());
461         return;
462     }
463
464     if (m_widgetState == WidgetState_Authorizing) {
465         LogWarning("Widget already authorizing, stop launchStep");
466         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
467                     NextStepEvent());
468         return;
469     }
470
471     m_dao.reset(new WrtDB::WidgetDAOReadOnly(DPL::FromASCIIString(m_tizenId)));
472     DPL::Optional<DPL::String> defloc = m_dao->getDefaultlocale();
473     if(!defloc.IsNull())
474     {
475         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(*defloc);
476     }
477
478     // For localizationsetting not changed on widget running
479     //LocalizationSetting::SetLanguageChangedCallback(
480     //        languageChangedCallback, this);
481
482     ADD_PROFILING_POINT("CreateWindow", "start");
483     m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid())));
484     ADD_PROFILING_POINT("CreateWindow", "stop");
485
486     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
487     ADD_PROFILING_POINT("Create splash screen", "start");
488     m_splashScreen.reset(
489             new SplashScreenSupport(m_windowData->m_win));
490     if (m_splashScreen->createSplashScreen(m_dao->getSplashImgSrc())) {
491         m_splashScreen->startSplashScreen();
492         cbs->progressFinish = DPL::MakeDelegate(this, &WrtClient::progressFinishCallback);
493     }
494     ADD_PROFILING_POINT("Create splash screen", "stop");
495     DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao);
496     m_widget->PrepareView(DPL::ToUTF8String(*startUrl),
497             m_windowData->m_win);
498     //you can't show window with splash screen before PrepareView
499     //ewk_view_add_with_context() in viewLogic breaks window
500
501     WrtDB::WidgetLocalizedInfo localizedInfo =
502         W3CFileLocalization::getLocalizedInfo(m_dao);
503     std:: string name = "";
504     if (!(localizedInfo.name.IsNull())) {
505         name = DPL::ToUTF8String(*(localizedInfo.name));
506     }
507     elm_win_title_set(m_windowData->m_win, name.c_str());
508     evas_object_show(m_windowData->m_win);
509     initializeWindowModes();
510     connectElmCallback();
511
512     if (!checkWACTestCertififedWidget())
513     {
514         LogWarning("WAC Certificate failed, stop launchStep");
515         return;
516     }
517
518     m_widgetState = WidgetState_Authorizing;
519     if (!m_widget->CheckBeforeLaunch()) {
520         LogError("CheckBeforeLaunch failed, stop launchStep");
521         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
522                     NextStepEvent());
523         return;
524     }
525     LogInfo("Widget launch accepted. Entering running state");
526     m_widgetState = WidgetState_Running;
527
528     cbs->loadFinish = DPL::MakeDelegate(this, &WrtClient::loadFinishCallback);
529     cbs->bufferSet = DPL::MakeDelegate(this, &WrtClient::setLayout);
530     cbs->bufferUnset = DPL::MakeDelegate(this, &WrtClient::unsetLayout);
531     cbs->webkitExit = DPL::MakeDelegate(this, &WrtClient::webkitExitCallback);
532     cbs->webCrash = DPL::MakeDelegate(this, &WrtClient::webCrashCallback);
533     cbs->toggleFullscreen = DPL::MakeDelegate(m_windowData.get(), &WindowData::toggleFullscreen);
534
535     m_widget->SetUserDelegates(cbs);
536     m_widget->Show();
537     m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
538     ADD_PROFILING_POINT("launchStep", "stop");
539 }
540
541 void WrtClient::initializeWindowModes()
542 {
543     Assert(m_windowData);
544     Assert(m_dao);
545     auto windowModes = m_dao->getWindowModes();
546     bool fullscreen = false;
547     bool backbutton = false;
548      if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
549          WidgetSettings widgetSettings;
550          m_dao->getWidgetSettings(widgetSettings);
551          WidgetSettingList settings(widgetSettings);
552         backbutton =
553             (settings.getBackButtonPresence() == BackButton_Enable);
554      }
555
556     FOREACH(it, windowModes)
557     {
558         std::string viewMode = DPL::ToUTF8String(*it);
559         if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
560             fullscreen = true;
561             break;
562         } else if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
563             break;
564         }
565     }
566
567     m_windowData->setViewMode(fullscreen,
568             backbutton);
569 }
570
571 void WrtClient::backButtonCallback(void* data,
572                                      Evas_Object * /*obj*/,
573                                      void * /*event_info*/)
574 {
575     LogInfo("BackButtonCallback");
576     Assert(data);
577
578     WrtClient* This = static_cast<WrtClient*>(data);
579
580     This->m_widget->Backward();
581 }
582
583 void WrtClient::connectElmCallback()
584 {
585     Assert(m_windowData);
586     Assert(m_dao);
587     if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
588         WidgetSettings widgetSettings;
589         m_dao->getWidgetSettings(widgetSettings);
590         WidgetSettingList settings(widgetSettings);
591         if (settings.getBackButtonPresence() == BackButton_Enable) {
592             m_windowData->addFloatBackButtonCallback(
593             "clicked",
594             &WrtClient::backButtonCallback,
595             this);
596         }
597
598         WidgetSettingScreenLock rotationValue = settings.getRotationValue();
599         if (rotationValue == Screen_Portrait) {
600             elm_win_rotation_with_resize_set(m_windowData->m_win, 0);
601         } else if (rotationValue == Screen_Landscape) {
602             elm_win_rotation_with_resize_set(m_windowData->m_win, 270);
603         } else {
604             elm_win_rotation_with_resize_set(m_windowData->m_win, 0);
605         }
606     }
607 }
608
609 void WrtClient::setLayout(Evas_Object* newBuffer) {
610     LogDebug("add new webkit buffer to window");
611     Assert(newBuffer);
612
613     elm_object_part_content_set(m_windowData->m_user_layout, ELM_SWALLOW_CONTENT, newBuffer);
614
615     evas_object_show(newBuffer);
616 }
617
618 void WrtClient::unsetLayout(Evas_Object* currentBuffer) {
619     LogDebug("remove current webkit buffer from window");
620     Assert(currentBuffer);
621     evas_object_hide(currentBuffer);
622
623     elm_object_part_content_unset(m_windowData->m_user_layout, ELM_SWALLOW_CONTENT);
624 }
625
626 void WrtClient::shutdownStep()
627 {
628     LogDebug("Closing Wrt connection ...");
629     if (m_initialized && m_widget) {
630         m_widgetState = WidgetState_Stopped;
631         m_widget->Hide();
632         m_widget.reset();
633         m_windowData.reset();
634         WRT::CoreModuleSingleton::Instance().Terminate();
635         m_initialized = false;
636     }
637     Quit();
638 }
639
640 int WrtClient::languageChangedCallback(void *data)
641 {
642     LogDebug("Language Changed");
643     if(!data)
644         return 0;
645     WrtClient* wrtClient = static_cast<WrtClient*>(data);
646     if(!(wrtClient->m_dao))
647         return 0;
648
649     // reset function fetches system locales and recreates language tags
650     LanguageTagsProviderSingleton::Instance().resetLanguageTags();
651     // widget default locales are added to language tags below
652     DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale();
653     if(!defloc.IsNull())
654     {
655         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(*defloc);
656     }
657
658     if (wrtClient->m_launched &&
659             wrtClient->m_widgetState != WidgetState_Stopped) {
660         wrtClient->m_widget->ReloadStartPage();
661     }
662     return 0;
663 }
664
665 void WrtClient::Quit()
666 {
667     ewk_shutdown();
668     DPL::Application::Quit();
669 }
670
671 int main(int argc,
672          char *argv[])
673 {
674     UNHANDLED_EXCEPTION_HANDLER_BEGIN
675     {
676         ADD_PROFILING_POINT("main-entered", "point");
677
678         // Set log tagging
679         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
680
681         // This code is to fork a web process without exec.
682         std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
683
684         if (!tizenId.empty())
685         {
686             LogDebug("Launching by fork mode");
687             ewk_init();
688             ewk_set_arguments(argc, argv);
689             setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
690             s_ewk_context = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
691         }
692
693         // Output on stdout will be flushed after every newline character,
694         // even if it is redirected to a pipe. This is useful for running
695         // from a script and parsing output.
696         // (Standard behavior of stdlib is to use full buffering when
697         // redirected to a pipe, which means even after an end of line
698         // the output may not be flushed).
699         setlinebuf(stdout);
700
701         // set evas backend type
702         if (!getenv("ELM_ENGINE")) {
703             if (!setenv("ELM_ENGINE", "gl", 1)) {
704                     LogDebug("Enable backend");
705             }
706         }
707         else {
708             LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
709         }
710
711     #ifndef TIZEN_PUBLIC
712         setenv("COREGL_FASTPATH", "1", 1);
713     #endif
714         setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
715         setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
716         setenv("ELM_IMAGE_CACHE", "0", 1);
717
718         WrtClient app(argc, argv);
719
720         ADD_PROFILING_POINT("Before appExec", "point");
721         int ret = app.Exec();
722         LogDebug("App returned: " << ret);
723         ret = app.getReturnStatus();
724         LogDebug("WrtClient returned: " << ret);
725         return ret;
726     }
727     UNHANDLED_EXCEPTION_HANDLER_END
728 }