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