Fix compatibility for x64 arch
[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 <aul.h>
18 #include <sys/time.h>
19 #include <sys/resource.h>
20 #include <appcore-efl.h>
21 #include <appcore-common.h>
22 #include <cstdlib>
23 #include <cstdio>
24 #include <string>
25 #include <dpl/log/log.h>
26 #include <dpl/optional_typedefs.h>
27 #include <dpl/exception.h>
28 #include <common/application_data.h>
29 #include <core_module.h>
30 #include <localization_setting.h>
31 #include <widget_deserialize_model.h>
32 #include <EWebKit2.h>
33 #include <dpl/localization/w3c_file_localization.h>
34 #include <dpl/localization/LanguageTagsProvider.h>
35 #include "webkit/injected-bundle/plugin_module_support.h"
36 #include <popup-runner/PopupInvoker.h>
37 #include <prepare_external_storage.h>
38 #include <vconf.h>
39
40 #include "process_pool.h"
41 #include "menu_db_util.h"
42 #include "launchpad_util.h"
43
44 //W3C PACKAGING enviroment variable name
45 #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
46
47 // window signal callback
48 const char *EDJE_SHOW_BACKWARD_SIGNAL = "show,backward,signal";
49 const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
50 const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized";
51 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
52 const char* const BUNDLE_PATH = LIBDIR_PREFIX "/libwrt-injected-bundle.so";
53 const char* const caCertPath = "/opt/usr/share/certs/ca-certificate.crt";
54
55 // process pool
56 const char* const DUMMY_PROCESS_PATH = "/usr/bin/wrt_launchpad_daemon_candidate";
57 static Ewk_Context* s_preparedEwkContext = NULL;
58 static WindowData*  s_preparedWindowData = NULL;
59 static int    app_argc = 0;
60 static char** app_argv = NULL;
61
62 // env
63 const char* const HOME = "HOME";
64 const char* const APP_HOME_PATH = "/opt/home/app";
65
66 WrtClient::WrtClient(int argc, char **argv) :
67     Application(argc, argv, "wrt-client", false),
68     DPL::TaskDecl<WrtClient>(this),
69     m_appControlIndex(DPL::OptionalUInt()),
70     m_launched(false),
71     m_initializing(false),
72     m_initialized(false),
73     m_sdkLauncherPid(0),
74     m_debugMode(false),
75     m_debuggerPort(0),
76     m_returnStatus(ReturnStatus::Succeeded),
77     m_widgetState(WidgetState::WidgetState_Stopped)
78 {
79     Touch();
80     LogDebug("App Created");
81 }
82
83 WrtClient::~WrtClient()
84 {
85     LogDebug("App Finished");
86 }
87
88 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
89 {
90     return m_returnStatus;
91 }
92
93 void WrtClient::OnStop()
94 {
95     LogInfo("Stopping Dummy Client");
96 }
97
98 void WrtClient::OnCreate()
99 {
100     LogInfo("On Create");
101     ADD_PROFILING_POINT("OnCreate callback", "point");
102     ewk_init();
103 }
104
105 void WrtClient::OnResume()
106 {
107     if (m_widgetState != WidgetState_Suspended) {
108         LogWarning("Widget is not suspended, resuming was skipped");
109         return;
110     }
111     m_widget->Resume();
112     m_widgetState = WidgetState_Running;
113 }
114
115 void WrtClient::OnPause()
116 {
117     if (m_widgetState != WidgetState_Running) {
118         LogWarning("Widget is not running to be suspended");
119         return;
120     }
121     m_widget->Suspend();
122     m_widgetState = WidgetState_Suspended;
123 }
124
125 void WrtClient::OnReset(bundle *b)
126 {
127     LogDebug("OnReset");
128     // bundle argument is freed after OnReset() is returned
129     // So bundle duplication is needed
130     ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
131     ApplicationDataSingleton::Instance().setEncodedBundle(b);
132
133     if (true == m_initializing) {
134         LogDebug("can not handle reset event");
135         return;
136     }
137     if (true == m_launched) {
138         if (m_widgetState == WidgetState_Stopped) {
139             LogError("Widget is not running to be reset");
140             return;
141         }
142         m_widget->Reset();
143         m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
144         m_widgetState = WidgetState_Running;
145     } else {
146         if (true == checkArgument()) {
147             setStep();
148         } else {
149             showHelpAndQuit();
150         }
151     }
152
153     // low memory callback set
154     appcore_set_event_callback(
155             APPCORE_EVENT_LOW_MEMORY,
156             WrtClient::appcoreLowMemoryCallback,
157             this);
158 }
159
160 void WrtClient::OnTerminate()
161 {
162     LogDebug("Wrt Shutdown now");
163     shutdownStep();
164 }
165
166 void WrtClient::showHelpAndQuit()
167 {
168     printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
169            "launch widgets.\n"
170            "Mandatory arguments to long options are mandatory for short "
171            "options too.\n"
172            "  -h,    --help                                 show this help\n"
173            "  -l,    --launch                               "
174            "launch widget with given tizen ID\n"
175            "  -t,    --tizen                                "
176            "launch widget with given tizen ID\n"
177            "\n");
178
179     Quit();
180 }
181
182 bool WrtClient::checkArgument()
183 {
184     std::string tizenId = getTizenIdFromArgument(m_argc, m_argv);
185
186     if (tizenId.empty()) {
187         // Just show help
188         return false;
189     } else {
190         std::size_t pos =
191             tizenId.find(WrtDB::AppControlPrefix::PROCESS_PREFIX);
192         if (pos != std::string::npos) {
193             std::string id = tizenId.substr(pos);
194             id.erase(strlen(WrtDB::AppControlPrefix::PROCESS_PREFIX));
195             std::stringstream s(id);
196             unsigned int appControlIndex;
197             s >> appControlIndex;
198             m_appControlIndex = appControlIndex;
199             tizenId.erase(pos);
200             LogDebug("app-control execute-index : " << appControlIndex);
201         }
202         m_tizenId = tizenId;
203         LogDebug("Tizen id: " << m_tizenId);
204         return true;
205     }
206 }
207
208 std::string WrtClient::getTizenIdFromArgument(int argc, char **argv)
209 {
210     LogInfo("checkArgument");
211     std::string arg = argv[0];
212
213     if (arg.empty()) {
214         return "";
215     }
216
217     if (arg.find("wrt-client") != std::string::npos) {
218         if (argc <= 1) {
219             return "";
220         }
221
222         arg = argv[1];
223
224         if (arg == "-h" || arg == "--help") {
225             return "";
226         } else if (arg == "-l" || arg == "--launch" ||
227                    arg == "-t" || arg == "--tizen")
228         {
229             if (argc != 3) {
230                 return "";
231             }
232             return argv[2];
233         } else {
234             return "";
235         }
236     } else {
237         // Launch widget based on application basename
238         size_t pos = arg.find_last_of('/');
239
240         if (pos != std::string::npos) {
241             arg = arg.erase(0, pos + 1);
242         }
243
244         return arg;
245     }
246 }
247
248 void WrtClient::setStep()
249 {
250     LogInfo("setStep");
251
252     AddStep(&WrtClient::initStep);
253
254     setSdkLauncherDebugData();
255
256     AddStep(&WrtClient::launchStep);
257     AddStep(&WrtClient::shutdownStep);
258
259     m_initializing = true;
260
261     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
262 }
263
264 void WrtClient::setSdkLauncherDebugData()
265 {
266     LogDebug("setSdkLauncherDebugData");
267
268     /* check bundle from sdk launcher */
269     bundle *bundleFromSdkLauncher;
270     bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
271     const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
272     const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
273     if (bundle_debug != NULL && bundle_pid != NULL) {
274         if (strcmp(bundle_debug, "true") == 0) {
275             m_debugMode = true;
276             m_sdkLauncherPid = atoi(bundle_pid);
277         } else {
278             m_debugMode = false;
279         }
280     }
281     bundle_free(bundleFromSdkLauncher);
282 }
283
284 bool WrtClient::checkDebugMode(SDKDebugData* debugData)
285 {
286     LogError("Checking for debug mode");
287     Assert(m_dao);
288
289     bool debugMode = debugData->debugMode;
290
291     LogInfo("[DEBUG_MODE] Widget is launched in " <<
292             (debugMode ? "DEBUG" : "RETAIL") <<
293             " mode.");
294
295     return debugMode;
296 }
297
298 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
299 {
300     LogDebug("Executing next step");
301     NextStep();
302 }
303
304 void WrtClient::initStep()
305 {
306     LogDebug("");
307     if (WRT::CoreModuleSingleton::Instance().Init()) {
308         m_initialized = true;
309     } else {
310         m_returnStatus = ReturnStatus::Failed;
311         SwitchToStep(&WrtClient::shutdownStep);
312     }
313
314     // ecore_event_jobs are processed sequentially without concession to
315     // other type events. To give a chance of execute to other events,
316     // ecore_timer_add was used.
317     DPL::Event::ControllerEventHandler<NextStepEvent>::PostTimedEvent(
318         NextStepEvent(), 0.001);
319 }
320
321 void WrtClient::loadFinishCallback(Evas_Object* webview)
322 {
323     ADD_PROFILING_POINT("loadFinishCallback", "start");
324     SDKDebugData* debug = new SDKDebugData;
325     debug->debugMode = m_debugMode;
326     debug->pid = new unsigned long(getpid());
327
328     LogInfo("Post result of launch");
329
330     // Start inspector server, if current mode is debugger mode.
331     // In the WK2 case, ewk_view_inspector_server_start should
332     // be called after WebProcess is created.
333     if (checkDebugMode(debug)) {
334         debug->portnum =
335             ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0);
336         if (debug->portnum == 0) {
337             LogWarning("Failed to get portnum");
338         } else {
339             LogInfo("Assigned port number for inspector : "
340                     << debug->portnum);
341         }
342     } else {
343         LogDebug("Debug mode is disabled");
344     }
345
346     //w3c packaging test debug (message on 4>)
347     const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
348     if (makeScreen != NULL && strcmp(makeScreen, "1") == 0) {
349         FILE* doutput = fdopen(4, "w");
350         fprintf(doutput, "didFinishLoadForFrameCallback: ready\n");
351         fclose(doutput);
352     }
353
354     if (webview) {
355         LogDebug("Launch succesfull");
356
357         m_launched = true;
358         m_initializing = false;
359         setlinebuf(stdout);
360         ADD_PROFILING_POINT("loadFinishCallback", "stop");
361         printf("launched\n");
362         fflush(stdout);
363     } else {
364         printf("failed\n");
365
366         m_returnStatus = ReturnStatus::Failed;
367         //shutdownStep
368         DPL::Event::ControllerEventHandler<NextStepEvent>::
369             PostEvent(NextStepEvent());
370     }
371
372     if (debug->debugMode) {
373         LogDebug("Send RT signal to wrt-launcher(pid: " << m_sdkLauncherPid);
374         union sigval sv;
375         /* send real time signal with result to wrt-launcher */
376         if (webview) {
377             LogDebug("userData->portnum : " << debug->portnum);
378             sv.sival_int = debug->portnum;
379         } else {
380             sv.sival_int = -1;
381         }
382         sigqueue(m_sdkLauncherPid, SIGRTMIN, sv);
383     }
384
385     ApplicationDataSingleton::Instance().freeBundle();
386
387     LogDebug("Cleaning wrtClient launch resources...");
388     delete debug->pid;
389     delete debug;
390 }
391
392 void WrtClient::progressFinishCallback()
393 {
394     m_splashScreen->stopSplashScreen();
395 }
396
397 void WrtClient::webkitExitCallback()
398 {
399     LogDebug("window close called, terminating app");
400     SwitchToStep(&WrtClient::shutdownStep);
401     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
402         NextStepEvent());
403 }
404
405 void WrtClient::webCrashCallback()
406 {
407     LogError("webProcess crashed");
408     SwitchToStep(&WrtClient::shutdownStep);
409     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
410         NextStepEvent());
411 }
412
413 void WrtClient::launchStep()
414 {
415     ADD_PROFILING_POINT("launchStep", "start");
416     LogDebug("Launching widget ...");
417
418     ADD_PROFILING_POINT("getRunnableWidgetObject", "start");
419     m_widget = WRT::CoreModuleSingleton::Instance()
420             .getRunnableWidgetObject(m_tizenId, m_appControlIndex);
421     ADD_PROFILING_POINT("getRunnableWidgetObject", "stop");
422
423     if (!m_widget) {
424         LogError("RunnableWidgetObject is NULL, stop launchStep");
425         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
426             NextStepEvent());
427         return;
428     }
429
430     if (m_widgetState == WidgetState_Running) {
431         LogWarning("Widget already running, stop launchStep");
432         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
433             NextStepEvent());
434         return;
435     }
436
437     if (m_widgetState == WidgetState_Authorizing) {
438         LogWarning("Widget already authorizing, stop launchStep");
439         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
440             NextStepEvent());
441         return;
442     }
443
444     m_dao.reset(new WrtDB::WidgetDAOReadOnly(DPL::FromASCIIString(m_tizenId)));
445     DPL::Optional<DPL::String> defloc = m_dao->getDefaultlocale();
446     if (!defloc.IsNull()) {
447         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
448             *defloc);
449     }
450
451     PrepareExternalStorageSingleton::Instance().Initialize(m_dao->getTizenPkgId());
452
453     /* remove language change callback */
454     /*
455     LocalizationSetting::SetLanguageChangedCallback(
456             languageChangedCallback, this);
457     */
458
459     ADD_PROFILING_POINT("CreateWindow", "start");
460     if (s_preparedWindowData == NULL) {
461         m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid()), true));
462     } else {
463         m_windowData.reset(s_preparedWindowData);
464         s_preparedWindowData = NULL;
465     }
466     ADD_PROFILING_POINT("CreateWindow", "stop");
467     evas_object_show(m_windowData->m_win);
468     // rotate window to initial value
469     setOrientationWindow();
470
471     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
472     ADD_PROFILING_POINT("Create splash screen", "start");
473     m_splashScreen.reset(
474         new SplashScreenSupport(m_windowData->m_win));
475     if (m_splashScreen->createSplashScreen(m_dao->getSplashImgSrc())) {
476         m_splashScreen->startSplashScreen();
477         cbs->progressFinish = DPL::MakeDelegate(
478                 this,
479                 &WrtClient::
480                     progressFinishCallback);
481     }
482     ADD_PROFILING_POINT("Create splash screen", "stop");
483     DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao);
484     if (!m_widget->PrepareView(DPL::ToUTF8String(*startUrl),
485             m_windowData->m_win, s_preparedEwkContext))
486     {
487         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
488             NextStepEvent());
489         return;
490     }
491     // send rotate information to ewk
492     setOrientationEwk();
493
494     //you can't show window with splash screen before PrepareView
495     //ewk_view_add_with_context() in viewLogic breaks window
496
497     m_windowData->init();
498
499     WrtDB::WidgetLocalizedInfo localizedInfo =
500         W3CFileLocalization::getLocalizedInfo(m_dao);
501     std::string name = "";
502     if (!(localizedInfo.name.IsNull())) {
503         name = DPL::ToUTF8String(*(localizedInfo.name));
504     }
505     elm_win_title_set(m_windowData->m_win, name.c_str());
506
507     initializeWindowModes();
508     connectElmCallback();
509
510     m_widgetState = WidgetState_Authorizing;
511     if (!m_widget->CheckBeforeLaunch()) {
512         LogError("CheckBeforeLaunch failed, stop launchStep");
513         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
514             NextStepEvent());
515         return;
516     }
517     LogInfo("Widget launch accepted. Entering running state");
518     m_widgetState = WidgetState_Running;
519
520     cbs->loadFinish = DPL::MakeDelegate(this, &WrtClient::loadFinishCallback);
521     cbs->bufferSet = DPL::MakeDelegate(this, &WrtClient::setLayout);
522     cbs->bufferUnset = DPL::MakeDelegate(this, &WrtClient::unsetLayout);
523     cbs->webkitExit = DPL::MakeDelegate(this, &WrtClient::webkitExitCallback);
524     cbs->webCrash = DPL::MakeDelegate(this, &WrtClient::webCrashCallback);
525     cbs->toggleFullscreen = DPL::MakeDelegate(
526             m_windowData.get(), &WindowData::toggleFullscreen);
527
528     m_widget->SetUserDelegates(cbs);
529     m_widget->Show();
530
531     m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
532
533     ADD_PROFILING_POINT("launchStep", "stop");
534 }
535
536 void WrtClient::initializeWindowModes()
537 {
538     Assert(m_windowData);
539     Assert(m_dao);
540     auto windowModes = m_dao->getWindowModes();
541     bool fullscreen = false;
542     bool backbutton = false;
543     if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
544         WrtDB::WidgetSettings widgetSettings;
545         m_dao->getWidgetSettings(widgetSettings);
546         WidgetSettingList settings(widgetSettings);
547         backbutton =
548             (settings.getBackButtonPresence() == BackButton_Enable);
549     }
550
551     FOREACH(it, windowModes)
552     {
553         std::string viewMode = DPL::ToUTF8String(*it);
554         if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
555             fullscreen = true;
556             break;
557         } else if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
558             break;
559         }
560     }
561
562     m_windowData->setViewMode(fullscreen,
563                               backbutton);
564 }
565
566 void WrtClient::backButtonCallback(void* data,
567                                    Evas_Object * /*obj*/,
568                                    void * /*event_info*/)
569 {
570     LogInfo("BackButtonCallback");
571     Assert(data);
572
573     WrtClient* This = static_cast<WrtClient*>(data);
574
575     This->m_widget->Backward();
576 }
577
578 int WrtClient::appcoreLowMemoryCallback(void* /*data*/)
579 {
580     LogInfo("appcoreLowMemoryCallback");
581     //WrtClient* This = static_cast<WrtClient*>(data);
582
583     // TODO call RunnableWidgetObject API regarding low memory
584     // The API should be implemented
585
586     return 0;
587 }
588
589 void WrtClient::setOrientationWindow(void)
590 {
591     Assert(m_windowData);
592     Assert(m_dao);
593
594     WrtDB::WidgetSettings widgetSettings;
595     m_dao->getWidgetSettings(widgetSettings);
596     WidgetSettingList settings(widgetSettings);
597     WidgetSettingScreenLock rotationValue = settings.getRotationValue();
598     if (rotationValue == Screen_Portrait) {
599         elm_win_wm_rotation_preferred_rotation_set(
600             m_windowData->m_win,
601             OrientationAngle::Window::Portrait::PRIMARY);
602     } else if (rotationValue == Screen_Landscape) {
603         elm_win_wm_rotation_preferred_rotation_set(
604             m_windowData->m_win,
605             OrientationAngle::Window::Landscape::PRIMARY);
606     } else if (rotationValue == Screen_AutoRotation) {
607         LogInfo("Nothing to do");
608     } else {
609         elm_win_wm_rotation_preferred_rotation_set(
610             m_windowData->m_win,
611             OrientationAngle::W3C::Portrait::PRIMARY);
612     }
613 }
614
615 void WrtClient::unsetOrientationWindow(void)
616 {
617     Assert(m_windowData);
618     Assert(m_dao);
619
620     WrtDB::WidgetSettings widgetSettings;
621     m_dao->getWidgetSettings(widgetSettings);
622     WidgetSettingList settings(widgetSettings);
623     WidgetSettingScreenLock rotationValue = settings.getRotationValue();
624     if (rotationValue == Screen_AutoRotation) {
625         LogInfo("Nothing to do");
626     }
627 }
628
629
630 void WrtClient::setOrientationEwk(void)
631 {
632     Assert(m_widget);
633     Assert(m_dao);
634
635     WrtDB::WidgetSettings widgetSettings;
636     m_dao->getWidgetSettings(widgetSettings);
637     WidgetSettingList settings(widgetSettings);
638     WidgetSettingScreenLock rotationValue = settings.getRotationValue();
639     if (rotationValue == Screen_Portrait) {
640         ewk_view_orientation_send(
641             m_widget->GetCurrentWebview(),
642              OrientationAngle::W3C::Portrait::PRIMARY);
643     } else if (rotationValue == Screen_Landscape) {
644         ewk_view_orientation_send(
645             m_widget->GetCurrentWebview(),
646             OrientationAngle::W3C::Landscape::PRIMARY);
647     } else if (rotationValue == Screen_AutoRotation) {
648          ewk_view_orientation_send(
649             m_widget->GetCurrentWebview(),
650             OrientationAngle::W3C::Portrait::PRIMARY);
651     } else {
652         ewk_view_orientation_send(
653             m_widget->GetCurrentWebview(),
654             OrientationAngle::W3C::Portrait::PRIMARY);
655     }
656 }
657
658 void WrtClient::ExitCallback(void* data,
659                                    Evas_Object * /*obj*/,
660                                    void * /*event_info*/)
661 {
662     LogInfo("ExitCallback");
663     Assert(data);
664
665     WrtClient* This = static_cast<WrtClient*>(data);
666
667     This->OnTerminate();
668 }
669
670
671 void WrtClient::connectElmCallback()
672 {
673     Assert(m_windowData);
674     Assert(m_dao);
675     WrtDB::WidgetSettings widgetSettings;
676     m_dao->getWidgetSettings(widgetSettings);
677     WidgetSettingList settings(widgetSettings);
678     if (settings.getBackButtonPresence() == BackButton_Enable) {
679         m_windowData->addFloatBackButtonCallback(
680             "clicked",
681             &WrtClient::backButtonCallback,
682             this);
683     }
684     evas_object_smart_callback_add(m_windowData->m_win,
685             "delete,request",
686             &WrtClient::ExitCallback,
687             this);
688 }
689
690 void WrtClient::setLayout(Evas_Object* newBuffer)
691 {
692     LogDebug("add new webkit buffer to window");
693     Assert(newBuffer);
694
695     elm_object_part_content_set(m_windowData->m_user_layout,
696                                 ELM_SWALLOW_CONTENT,
697                                 newBuffer);
698
699     evas_object_show(newBuffer);
700 }
701
702 void WrtClient::unsetLayout(Evas_Object* currentBuffer)
703 {
704     LogDebug("remove current webkit buffer from window");
705     Assert(currentBuffer);
706     evas_object_hide(currentBuffer);
707
708     elm_object_part_content_unset(m_windowData->m_user_layout,
709                                   ELM_SWALLOW_CONTENT);
710 }
711
712 void WrtClient::shutdownStep()
713 {
714     LogDebug("Closing Wrt connection ...");
715
716     if (m_widget && m_widgetState) {
717         m_widgetState = WidgetState_Stopped;
718         m_widget->Hide();
719         // AutoRotation use m_widget pointer internally.
720         // It must be unset before m_widget is released.
721         unsetOrientationWindow();
722         m_widget.reset();
723         ewk_context_delete(s_preparedEwkContext);
724         PrepareExternalStorageSingleton::Instance().Deinitialize();
725         WRT::CoreModuleSingleton::Instance().Terminate();
726     }
727     if (m_initialized) {
728         m_initialized = false;
729     }
730     m_windowData.reset();
731     Quit();
732 }
733
734 int WrtClient::languageChangedCallback(void *data)
735 {
736     LogDebug("Language Changed");
737     if (!data) {
738         return 0;
739     }
740     WrtClient* wrtClient = static_cast<WrtClient*>(data);
741     if (!(wrtClient->m_dao)) {
742         return 0;
743     }
744
745     // reset function fetches system locales and recreates language tags
746     LanguageTagsProviderSingleton::Instance().resetLanguageTags();
747     // widget default locales are added to language tags below
748     DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale();
749     if (!defloc.IsNull()) {
750         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
751             *defloc);
752     }
753
754     if (wrtClient->m_launched &&
755         wrtClient->m_widgetState != WidgetState_Stopped)
756     {
757         wrtClient->m_widget->ReloadStartPage();
758     }
759     return 0;
760 }
761
762 void WrtClient::Quit()
763 {
764     ewk_shutdown();
765     DPL::Application::Quit();
766 }
767
768 static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler)
769 {
770     int fd = ecore_main_fd_handler_fd_get(handler);
771
772     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
773     {
774         LogDebug("ECORE_FD_ERROR");
775
776         if (fd != -1)
777         {
778             close(fd);
779         }
780
781         exit(-1);
782         return ECORE_CALLBACK_CANCEL;
783     }
784
785     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
786     {
787         LogDebug("ECORE_FD_READ");
788         {
789             app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
790             memset(pkt, 0, AUL_SOCK_MAXBUFF);
791
792             int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
793
794             if (fd != -1)
795             {
796                 close(fd);
797             }
798
799             if (recv_ret == -1)
800             {
801                 LogDebug("recv error!");
802                 exit(-1);
803             }
804             LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len);
805
806             ecore_main_fd_handler_del(handler);
807
808             __wrt_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv);
809
810             free(pkt);
811         }
812
813         ecore_main_loop_quit();
814         return ECORE_CALLBACK_CANCEL;
815     }
816
817     return ECORE_CALLBACK_CANCEL;
818 }
819
820 static void vconf_changed_handler(keynode_t* /*key*/, void* /*data*/)
821 {
822     LogInfo("VCONFKEY_LANGSET vconf-key was changed!");
823
824     // When system language is changed, the candidate process will be created again.
825     exit(-1);
826 }
827
828 void set_env()
829 {
830     // set evas backend type
831     if (!getenv("ELM_ENGINE"))
832     {
833         if (!setenv("ELM_ENGINE", "gl", 1))
834         {
835             LogDebug("Enable backend");
836         }
837     }
838     else
839     {
840         LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
841     }
842
843 #ifndef TIZEN_PUBLIC
844     setenv("COREGL_FASTPATH", "1", 1);
845 #endif
846     setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
847     setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
848     setenv("ELM_IMAGE_CACHE", "0", 1);
849 }
850
851 int main(int argc,
852          char *argv[])
853 {
854     // process pool - store arg's value
855     app_argc = argc;
856     app_argv = argv;
857
858     UNHANDLED_EXCEPTION_HANDLER_BEGIN
859     {
860         ADD_PROFILING_POINT("main-entered", "point");
861
862         // Set log tagging
863         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
864
865         // Set environment variables
866         set_env();
867
868         if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d"))
869         {
870             LogInfo("Entered dummy process mode");
871             sprintf(argv[0], "%s                                              ",
872                     DUMMY_PROCESS_PATH);
873
874             LogInfo("Prepare ewk_context");
875             appcore_set_i18n("wrt-client", NULL);
876             ewk_set_arguments(argc, argv);
877             setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
878             s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
879
880             if (s_preparedEwkContext == NULL)
881             {
882                 LogInfo("Creating webkit context was failed!");
883                 exit(-1);
884             }
885
886             int client_fd = __connect_process_pool_server();
887
888             if (client_fd == -1)
889             {
890                 LogInfo("Connecting process_pool_server was failed!");
891                 exit(-1);
892             }
893
894             // register language changed callback
895             vconf_notify_key_changed(VCONFKEY_LANGSET, vconf_changed_handler, NULL);
896
897             LogInfo("Prepare window_data");
898             // Temporarily change HOME path to app
899             // This change is needed for getting elementary profile
900             // /opt/home/app/.elementary/config/mobile/base.cfg
901             const char* backupEnv = getenv(HOME);
902             setenv(HOME, APP_HOME_PATH, 1);
903             LogInfo("elm_init()");
904             elm_init(argc, argv);
905             setenv(HOME, backupEnv, 1);
906
907             LogInfo("WindowData()");
908             s_preparedWindowData = new WindowData(static_cast<unsigned long>(getpid()));
909
910             Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd,
911                                            (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR),
912                                            proces_pool_fd_handler, NULL, NULL, NULL);
913
914             if (fd_handler == NULL)
915             {
916                 LogInfo("fd_handler is NULL");
917                 exit(-1);
918             }
919
920             setpriority(PRIO_PROCESS, 0, 0);
921
922             LogDebug("ecore_main_loop_begin()");
923             ecore_main_loop_begin();
924             LogDebug("ecore_main_loop_begin()_end");
925
926             // deregister language changed callback
927             vconf_ignore_key_changed(VCONFKEY_LANGSET, vconf_changed_handler);
928
929             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
930             PluginModuleSupport::init(s_preparedEwkContext, tizenId);
931         }
932         else
933         {
934             // This code is to fork a web process without exec.
935             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
936             if (!tizenId.empty()) {
937                 std::size_t pos =
938                     tizenId.find(WrtDB::AppControlPrefix::PROCESS_PREFIX);
939                 if (pos != std::string::npos) {
940                     tizenId.erase(pos);
941                 }
942
943                 LogDebug("Launching by fork mode");
944                 // Language env setup
945                 appcore_set_i18n("wrt-client", NULL);
946                 ewk_set_arguments(argc, argv);
947                 setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
948                 s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
949                         BUNDLE_PATH);
950
951                 if (s_preparedEwkContext == NULL)
952                 {
953                     LogInfo("Creating webkit context was failed!");
954                     Wrt::Popup::PopupInvoker().showInfo("Error", "Creating webkit context was failed.", "OK");
955                     exit(-1);
956                 }
957
958                 // plugin init
959                 PluginModuleSupport::init(s_preparedEwkContext, tizenId);
960
961             }
962         }
963
964         // Output on stdout will be flushed after every newline character,
965         // even if it is redirected to a pipe. This is useful for running
966         // from a script and parsing output.
967         // (Standard behavior of stdlib is to use full buffering when
968         // redirected to a pipe, which means even after an end of line
969         // the output may not be flushed).
970         setlinebuf(stdout);
971
972         WrtClient app(app_argc, app_argv);
973
974         ADD_PROFILING_POINT("Before appExec", "point");
975         int ret = app.Exec();
976         LogDebug("App returned: " << ret);
977         ret = app.getReturnStatus();
978         LogDebug("WrtClient returned: " << ret);
979         return ret;
980     }
981     UNHANDLED_EXCEPTION_HANDLER_END
982 }