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