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