Remove "app2sd" build dependency
[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 <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 <popup-runner/PopupInvoker.h>
36 #include <vconf.h>
37 #include "auto_rotation_support.h"
38
39 #include <process_pool.h>
40 #include <process_pool_launchpad_util.h>
41
42 #include "client_command_line_parser.h"
43 #include "client_ide_support.h"
44 #include "client_security_support.h"
45 #include "client_service_support.h"
46 #include "client_submode_support.h"
47
48 //W3C PACKAGING enviroment variable name
49 #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
50
51 // window signal callback
52 const char *EDJE_SHOW_PROGRESS_SIGNAL = "show,progress,signal";
53 const char *EDJE_HIDE_PROGRESS_SIGNAL = "hide,progress,signal";
54 const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
55 const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized";
56 const std::string VIEWMODE_TYPE_WINDOWED = "windowed";
57 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
58 const char* const BUNDLE_PATH = LIBDIR_PREFIX "/usr/lib/libwrt-injected-bundle.so";
59 const char* const MESSAGE_NAME_INITIALIZE = "ToInjectedBundle::INIT";
60 const unsigned int UID_ROOT = 0;
61
62 // process pool
63 const char* const DUMMY_PROCESS_PATH = "/usr/bin/wrt_launchpad_daemon_candidate";
64 static Ewk_Context* s_preparedEwkContext = NULL;
65 static WindowData*  s_preparedWindowData = NULL;
66 static int    app_argc = 0;
67 static char** app_argv = NULL;
68
69 // env
70 const char* const HOME = "HOME";
71 const char* const APP_HOME_PATH = "/opt/home/app";
72 const char* const ROOT_HOME_PATH = "/opt/home/root";
73
74 WrtClient::WrtClient(int argc, char **argv) :
75     Application(argc, argv, "wrt-client", false),
76     DPL::TaskDecl<WrtClient>(this),
77     m_launched(false),
78     m_initializing(false),
79     m_initialized(false),
80     m_debugMode(false),
81     m_returnStatus(ReturnStatus::Succeeded),
82     m_widgetState(WidgetState::WidgetState_Stopped),
83     m_initialViewMode(VIEWMODE_TYPE_MAXIMIZED),
84     m_currentViewMode(VIEWMODE_TYPE_MAXIMIZED),
85     m_isWebkitFullscreen(false),
86     m_isFullscreenByPlatform(false),
87     m_submodeSupport(new ClientModule::SubmodeSupport())
88 {
89     Touch();
90     LogDebug("App Created");
91 }
92
93 WrtClient::~WrtClient()
94 {
95     LogDebug("App Finished");
96 }
97
98 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
99 {
100     return m_returnStatus;
101 }
102
103 void WrtClient::OnStop()
104 {
105     LogDebug("Stopping Dummy Client");
106 }
107
108 void WrtClient::OnCreate()
109 {
110     LogDebug("On Create");
111     ADD_PROFILING_POINT("OnCreate callback", "point");
112     ewk_init();
113 }
114
115 void WrtClient::OnResume()
116 {
117     if (m_widgetState != WidgetState_Suspended) {
118         LogWarning("Widget is not suspended, resuming was skipped");
119         return;
120     }
121     m_widget->Resume();
122     m_widgetState = WidgetState_Running;
123 }
124
125 void WrtClient::OnPause()
126 {
127     if (m_widgetState != WidgetState_Running) {
128         LogWarning("Widget is not running to be suspended");
129         return;
130     }
131     if (m_submodeSupport->isNeedTerminateOnSuspend()) {
132         LogDebug("Current mode cannot support suspend");
133         elm_exit();
134         return;
135     }
136     m_widget->Suspend();
137     m_widgetState = WidgetState_Suspended;
138 }
139
140 void WrtClient::OnReset(bundle *b)
141 {
142     LogDebug("OnReset");
143     // bundle argument is freed after OnReset() is returned
144     // So bundle duplication is needed
145     ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
146     ApplicationDataSingleton::Instance().setEncodedBundle(b);
147
148     if (true == m_initializing) {
149         LogDebug("can not handle reset event");
150         return;
151     }
152     if (true == m_launched) {
153         if (m_widgetState == WidgetState_Stopped) {
154             LogError("Widget is not running to be reset");
155             return;
156         }
157         m_widget->Reset();
158         m_widgetState = WidgetState_Running;
159     } else {
160         m_tizenId =
161             ClientModule::CommandLineParser::getTizenId(m_argc, m_argv);
162         if (m_tizenId.empty()) {
163             showHelpAndQuit();
164         } else {
165             setDebugMode(b);
166             setStep();
167         }
168     }
169
170     // low memory callback set
171     appcore_set_event_callback(
172             APPCORE_EVENT_LOW_MEMORY,
173             WrtClient::appcoreLowMemoryCallback,
174             this);
175 }
176
177 void WrtClient::OnTerminate()
178 {
179     LogDebug("Wrt Shutdown now");
180     shutdownStep();
181 }
182
183 void WrtClient::showHelpAndQuit()
184 {
185     printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
186            "launch widgets.\n"
187            "Mandatory arguments to long options are mandatory for short "
188            "options too.\n"
189            "  -h,    --help                                 show this help\n"
190            "  -l,    --launch                               "
191            "launch widget with given tizen ID\n"
192            "  -t,    --tizen                                "
193            "launch widget with given tizen ID\n"
194            "\n");
195
196     Quit();
197 }
198
199 void WrtClient::setStep()
200 {
201     LogDebug("setStep");
202
203     AddStep(&WrtClient::initStep);
204     AddStep(&WrtClient::launchStep);
205     AddStep(&WrtClient::shutdownStep);
206
207     m_initializing = true;
208
209     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
210 }
211
212 void WrtClient::setDebugMode(bundle* b)
213 {
214     m_debugMode = ClientModule::IDESupport::getDebugMode(b);
215     LogDebug("debug mode : " << m_debugMode);
216 }
217
218 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
219 {
220     LogDebug("Executing next step");
221     NextStep();
222 }
223
224 void WrtClient::initStep()
225 {
226     LogDebug("");
227     if (WRT::CoreModuleSingleton::Instance().Init()) {
228         m_initialized = true;
229     } else {
230         m_returnStatus = ReturnStatus::Failed;
231         SwitchToStep(&WrtClient::shutdownStep);
232     }
233
234     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
235 }
236
237 void WrtClient::loadFinishCallback(Evas_Object* webview)
238 {
239     ADD_PROFILING_POINT("loadFinishCallback", "start");
240
241     // Splash screen
242     if (m_splashScreen && m_splashScreen->isShowing())
243     {
244         m_splashScreen->stopSplashScreenBuffered();
245     }
246
247     LogDebug("Post result of launch");
248
249     //w3c packaging test debug (message on 4>)
250     const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
251     if (makeScreen != NULL && strcmp(makeScreen, "1") == 0) {
252         FILE* doutput = fdopen(4, "w");
253         fprintf(doutput, "didFinishLoadForFrameCallback: ready\n");
254         fclose(doutput);
255     }
256
257     if (webview) {
258         LogDebug("Launch succesfull");
259
260         m_launched = true;
261         m_initializing = false;
262         setlinebuf(stdout);
263         ADD_PROFILING_POINT("loadFinishCallback", "stop");
264         printf("launched\n");
265         fflush(stdout);
266     } else {
267         printf("failed\n");
268
269         m_returnStatus = ReturnStatus::Failed;
270         //shutdownStep
271         DPL::Event::ControllerEventHandler<NextStepEvent>::
272             PostEvent(NextStepEvent());
273     }
274
275     if (m_debugMode) {
276         unsigned int portNum =
277             ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0);
278         LogDebug("Port for inspector : " << portNum);
279         bool ret = ClientModule::IDESupport::sendReply(
280                        ApplicationDataSingleton::Instance().getBundle(),
281                        portNum);
282         if (!ret) {
283             LogWarning("Fail to send reply");
284         }
285     }
286
287     ApplicationDataSingleton::Instance().freeBundle();
288 }
289
290 void WrtClient::resetCallback(bool result)
291 {
292     if (!result) {
293         LogDebug("Fail to handle reset event");
294         // free bundle data
295         ApplicationDataSingleton::Instance().freeBundle();
296     }
297 }
298
299 void WrtClient::progressStartedCallback()
300 {
301     if (m_settingList->getProgressBarPresence() == ProgressBar_Enable ||
302         m_currentViewMode == VIEWMODE_TYPE_WINDOWED)
303     {
304         m_windowData->signalEmit(Layer::MAIN_LAYOUT,
305                                  EDJE_SHOW_PROGRESS_SIGNAL,
306                                  "");
307         m_windowData->updateProgress(0);
308     }
309 }
310
311 void WrtClient::loadProgressCallback(Evas_Object* /*webview*/, double value)
312 {
313     if (m_settingList->getProgressBarPresence() == ProgressBar_Enable ||
314         m_currentViewMode == VIEWMODE_TYPE_WINDOWED)
315     {
316         m_windowData->updateProgress(value);
317     }
318 }
319
320 void WrtClient::progressFinishCallback()
321 {
322     if (m_settingList->getProgressBarPresence() == ProgressBar_Enable ||
323         m_currentViewMode == VIEWMODE_TYPE_WINDOWED)
324     {
325         m_windowData->signalEmit(Layer::MAIN_LAYOUT,
326                                  EDJE_HIDE_PROGRESS_SIGNAL,
327                                  "");
328     }
329 }
330
331 void WrtClient::webkitExitCallback()
332 {
333     LogDebug("window close called, terminating app");
334     SwitchToStep(&WrtClient::shutdownStep);
335     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
336         NextStepEvent());
337 }
338
339 void WrtClient::webCrashCallback()
340 {
341     LogError("webProcess crashed");
342     SwitchToStep(&WrtClient::shutdownStep);
343     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
344         NextStepEvent());
345 }
346
347 void WrtClient::enterFullscreenCallback(Evas_Object* /*obj*/,
348                                         bool isFullscreenByPlatform)
349 {
350     // enter fullscreen
351     m_windowData->toggleFullscreen(true);
352     m_currentViewMode = VIEWMODE_TYPE_FULLSCREEN;
353     m_isWebkitFullscreen = true;
354     if (isFullscreenByPlatform) {
355         m_isFullscreenByPlatform = true;
356     }
357 }
358
359 void WrtClient::exitFullscreenCallback(Evas_Object* /*obj*/)
360 {
361     // exit fullscreen
362     m_windowData->toggleFullscreen(false);
363     m_currentViewMode = m_initialViewMode;
364     m_isWebkitFullscreen = false;
365     m_isFullscreenByPlatform = false;
366 }
367
368 void WrtClient::launchStep()
369 {
370     ADD_PROFILING_POINT("launchStep", "start");
371     LogDebug("Launching widget ...");
372
373     ADD_PROFILING_POINT("getRunnableWidgetObject", "start");
374     m_widget = WRT::CoreModuleSingleton::Instance()
375             .getRunnableWidgetObject(m_tizenId);
376     ADD_PROFILING_POINT("getRunnableWidgetObject", "stop");
377
378     if (!m_widget) {
379         LogError("RunnableWidgetObject is NULL, stop launchStep");
380         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
381             NextStepEvent());
382         return;
383     }
384
385     if (m_widgetState == WidgetState_Running) {
386         LogWarning("Widget already running, stop launchStep");
387         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
388             NextStepEvent());
389         return;
390     }
391
392     if (m_widgetState == WidgetState_Authorizing) {
393         LogWarning("Widget already authorizing, stop launchStep");
394         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
395             NextStepEvent());
396         return;
397     }
398
399     m_dao.reset(new WrtDB::WidgetDAOReadOnly(DPL::FromASCIIString(m_tizenId)));
400     WrtDB::WidgetSettings widgetSettings;
401     m_dao->getWidgetSettings(widgetSettings);
402     m_settingList.reset(new WidgetSettingList(widgetSettings));
403     m_submodeSupport->initialize(DPL::FromASCIIString(m_tizenId));
404
405     DPL::Optional<DPL::String> defloc = m_dao->getDefaultlocale();
406     if (!defloc.IsNull()) {
407         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
408             *defloc);
409     }
410
411     setInitialViewMode();
412
413     /* remove language change callback */
414     /*
415     LocalizationSetting::SetLanguageChangedCallback(
416             languageChangedCallback, this);
417     */
418
419     ADD_PROFILING_POINT("CreateWindow", "start");
420     if (s_preparedWindowData == NULL) {
421         m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid()), true));
422     } else {
423         m_windowData.reset(s_preparedWindowData);
424         s_preparedWindowData = NULL;
425     }
426     ADD_PROFILING_POINT("CreateWindow", "stop");
427     if (!m_windowData->initScreenReaderSupport(
428             m_settingList->getAccessibility() == Accessibility_Enable))
429     {
430         LogWarning("Fail to set screen reader support set");
431     }
432
433     // rotate window to initial value
434     setWindowInitialOrientation();
435     setCtxpopupItem();
436
437     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
438
439     ADD_PROFILING_POINT("Create splash screen", "start");
440     DPL::OptionalString splashImgSrc = m_dao->getSplashImgSrc();
441     if (!splashImgSrc.IsNull())
442     {
443         m_splashScreen.reset(
444             new SplashScreenSupport(
445                 m_windowData->getEvasObject(Layer::WINDOW),
446                 (DPL::ToUTF8String(*splashImgSrc)).c_str(),
447                 m_currentViewMode != VIEWMODE_TYPE_FULLSCREEN,
448                 m_settingList->getRotationValue() == Screen_Landscape));
449         m_splashScreen->startSplashScreen();
450     }
451     ADD_PROFILING_POINT("Create splash screen", "stop");
452
453     DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao);
454     if (!m_widget->PrepareView(
455             DPL::ToUTF8String(*startUrl),
456             m_windowData->getEvasObject(Layer::WINDOW),
457             s_preparedEwkContext))
458     {
459         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
460             NextStepEvent());
461         return;
462     }
463     // send rotate information to ewk
464     setEwkInitialOrientation();
465
466     //you can't show window with splash screen before PrepareView
467     //ewk_view_add_with_context() in viewLogic breaks window
468     m_windowData->init();
469     m_windowData->postInit();
470
471     // sub-mode support
472     if (m_submodeSupport->isInlineMode()) {
473         if (m_submodeSupport->transientWindow(
474                 elm_win_xwindow_get(
475                     m_windowData->getEvasObject(Layer::WINDOW))))
476         {
477             LogDebug("Success to set submode");
478         } else {
479             LogWarning("Fail to set submode");
480         }
481     }
482     m_windowData->smartCallbackAdd(Layer::FOCUS,
483                                    "focused",
484                                    focusedCallback,
485                                    this);
486     m_windowData->smartCallbackAdd(Layer::FOCUS,
487                                    "unfocused",
488                                    unfocusedCallback,
489                                    this);
490
491     WrtDB::WidgetLocalizedInfo localizedInfo =
492         W3CFileLocalization::getLocalizedInfo(m_dao);
493     std::string name = "";
494     if (!(localizedInfo.name.IsNull())) {
495         name = DPL::ToUTF8String(*(localizedInfo.name));
496     }
497     elm_win_title_set(m_windowData->getEvasObject(Layer::WINDOW),
498                       name.c_str());
499
500     // window show
501     evas_object_show(m_windowData->getEvasObject(Layer::WINDOW));
502
503     initializeWindowModes();
504
505     m_widgetState = WidgetState_Authorizing;
506     if (!m_widget->CheckBeforeLaunch()) {
507         LogError("CheckBeforeLaunch failed, stop launchStep");
508         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
509             NextStepEvent());
510         return;
511     }
512     LogDebug("Widget launch accepted. Entering running state");
513     m_widgetState = WidgetState_Running;
514
515     cbs->progressStarted = DPL::MakeDelegate(this, &WrtClient::progressStartedCallback);
516     cbs->progress = DPL::MakeDelegate(this, &WrtClient::loadProgressCallback);
517     cbs->progressFinish = DPL::MakeDelegate(this, &WrtClient::progressFinishCallback);
518     cbs->loadFinish = DPL::MakeDelegate(this, &WrtClient::loadFinishCallback);
519     cbs->reset = DPL::MakeDelegate(this, &WrtClient::resetCallback);
520     cbs->bufferSet = DPL::MakeDelegate(this, &WrtClient::setLayout);
521     cbs->bufferUnset = DPL::MakeDelegate(this, &WrtClient::unsetLayout);
522     cbs->webkitExit = DPL::MakeDelegate(this, &WrtClient::webkitExitCallback);
523     cbs->webCrash = DPL::MakeDelegate(this, &WrtClient::webCrashCallback);
524     cbs->enterFullscreen = DPL::MakeDelegate(this, &WrtClient::enterFullscreenCallback);
525     cbs->exitFullscreen = DPL::MakeDelegate(this, &WrtClient::exitFullscreenCallback);
526     cbs->setOrientation = DPL::MakeDelegate(this, &WrtClient::setWindowOrientation);
527     cbs->hwkey = DPL::MakeDelegate(this, &WrtClient::hwkeyCallback);
528
529     m_widget->SetUserDelegates(cbs);
530     m_widget->Show();
531
532     ADD_PROFILING_POINT("launchStep", "stop");
533 }
534
535 void WrtClient::initializeWindowModes()
536 {
537     Assert(m_windowData);
538     bool backbutton =
539         (m_settingList->getBackButtonPresence() == BackButton_Enable ||
540         m_currentViewMode == VIEWMODE_TYPE_WINDOWED);
541     m_windowData->setViewMode(m_currentViewMode == VIEWMODE_TYPE_FULLSCREEN,
542                               backbutton);
543 }
544
545 Eina_Bool WrtClient::naviframeBackButtonCallback(void* data,
546                                                  Elm_Object_Item* /*it*/)
547 {
548     LogDebug("BackButtonCallback");
549     Assert(data);
550
551     WrtClient* This = static_cast<WrtClient*>(data);
552     This->m_widget->Backward();
553     return EINA_FALSE;
554 }
555
556 int WrtClient::appcoreLowMemoryCallback(void* /*data*/)
557 {
558     LogDebug("appcoreLowMemoryCallback");
559     //WrtClient* This = static_cast<WrtClient*>(data);
560
561     // TODO call RunnableWidgetObject API regarding low memory
562     // The API should be implemented
563
564     // temporary solution because we have no way to get ewk_context from runnable object.
565     if (s_preparedEwkContext)
566     {
567         ewk_context_cache_clear(s_preparedEwkContext);
568         ewk_context_notify_low_memory(s_preparedEwkContext);
569     }
570
571     return 0;
572 }
573
574 void WrtClient::setInitialViewMode(void)
575 {
576     Assert(m_dao);
577     WrtDB::WindowModeList windowModes = m_dao->getWindowModes();
578     FOREACH(it, windowModes) {
579         std::string viewMode = DPL::ToUTF8String(*it);
580         switch(viewMode[0]) {
581             case 'f':
582                 if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
583                     m_initialViewMode = viewMode;
584                     m_currentViewMode = m_initialViewMode;
585                     break;
586                 }
587                 break;
588             case 'm':
589                 if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
590                     m_initialViewMode = viewMode;
591                     m_currentViewMode = m_initialViewMode;
592                     break;
593                 }
594                 break;
595             case 'w':
596                 if (viewMode == VIEWMODE_TYPE_WINDOWED) {
597                     m_initialViewMode = viewMode;
598                     m_currentViewMode = m_initialViewMode;
599                     break;
600                 }
601                 break;
602             default:
603                 break;
604         }
605     }
606 }
607
608 void WrtClient::setWindowInitialOrientation(void)
609 {
610     Assert(m_windowData);
611     Assert(m_dao);
612
613     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
614     if (rotationValue == Screen_Portrait) {
615         setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY);
616     } else if (rotationValue == Screen_Landscape) {
617         setWindowOrientation(OrientationAngle::Window::Landscape::PRIMARY);
618     } else if (rotationValue == Screen_AutoRotation) {
619         if (!AutoRotationSupport::setAutoRotation(
620                 m_windowData->getEvasObject(Layer::WINDOW),
621                 autoRotationCallback,
622                 this))
623         {
624             LogError("Fail to set auto rotation");
625         }
626     } else {
627         setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY);
628     }
629 }
630
631 void WrtClient::setWindowOrientation(int angle)
632 {
633     Assert(m_windowData);
634     m_windowData->setOrientation(angle);
635 }
636
637 void WrtClient::unsetWindowOrientation(void)
638 {
639     Assert(m_windowData);
640     Assert(m_dao);
641
642     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
643     if (rotationValue == Screen_AutoRotation) {
644         AutoRotationSupport::unsetAutoRotation(
645             m_windowData->getEvasObject(Layer::WINDOW),
646             autoRotationCallback);
647     }
648 }
649
650 void WrtClient::setEwkInitialOrientation(void)
651 {
652     Assert(m_widget);
653     Assert(m_dao);
654
655     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
656     if (rotationValue == Screen_Portrait) {
657         ewk_view_orientation_send(
658             m_widget->GetCurrentWebview(),
659              OrientationAngle::W3C::Portrait::PRIMARY);
660     } else if (rotationValue == Screen_Landscape) {
661         ewk_view_orientation_send(
662             m_widget->GetCurrentWebview(),
663             OrientationAngle::W3C::Landscape::PRIMARY);
664     } else if (rotationValue == Screen_AutoRotation) {
665          ewk_view_orientation_send(
666             m_widget->GetCurrentWebview(),
667             OrientationAngle::W3C::Portrait::PRIMARY);
668     } else {
669         ewk_view_orientation_send(
670             m_widget->GetCurrentWebview(),
671             OrientationAngle::W3C::Portrait::PRIMARY);
672     }
673 }
674
675 void WrtClient::ExitCallback(void* data,
676                                    Evas_Object * /*obj*/,
677                                    void * /*event_info*/)
678 {
679     LogInfo("ExitCallback");
680     Assert(data);
681
682     WrtClient* This = static_cast<WrtClient*>(data);
683
684     This->OnTerminate();
685 }
686
687 void WrtClient::setCtxpopupItem(void)
688 {
689     WindowData::CtxpopupItemDataList data;
690
691     // 1. share
692     WindowData::CtxpopupCallbackType shareCallback =
693         DPL::MakeDelegate(this, &WrtClient::ctxpopupShare);
694     WindowData::CtxpopupItemData shareData("Share",
695                                            std::string(),
696                                            shareCallback);
697
698     // 2. reload
699     WindowData::CtxpopupCallbackType reloadCallback =
700         DPL::MakeDelegate(this, &WrtClient::ctxpopupReload);
701     WindowData::CtxpopupItemData reloadData("Reload",
702                                             std::string(),
703                                             reloadCallback);
704
705     // 3. Open in browser
706     WindowData::CtxpopupCallbackType launchBrowserCallback =
707         DPL::MakeDelegate(this, &WrtClient::ctxpopupLaunchBrowser);
708     WindowData::CtxpopupItemData launchBrowserData("Open in browser",
709                                                    std::string(),
710                                                    launchBrowserCallback);
711     data.push_back(shareData);
712     data.push_back(reloadData);
713     data.push_back(launchBrowserData);
714     m_windowData->setCtxpopupItemData(data);
715 }
716
717 void WrtClient::ctxpopupShare(void)
718 {
719     LogDebug("share");
720     const char* url = ewk_view_url_get(m_widget->GetCurrentWebview());
721     if (!url) {
722         LogError("url is empty");
723         return;
724     }
725     if (ClientModule::ServiceSupport::launchShareService(
726             elm_win_xwindow_get(m_windowData->getEvasObject(Layer::WINDOW)),
727             url))
728     {
729         LogDebug("success");
730     } else {
731         LogDebug("fail");
732     }
733     evas_object_smart_callback_add(m_windowData->m_win,
734             "delete,request",
735             &WrtClient::ExitCallback,
736             this);
737 }
738
739 void WrtClient::ctxpopupReload(void)
740 {
741     LogDebug("reload");
742     ewk_view_reload(m_widget->GetCurrentWebview());
743 }
744
745 void WrtClient::ctxpopupLaunchBrowser(void)
746 {
747     LogDebug("launchBrowser");
748     const char* url = ewk_view_url_get(m_widget->GetCurrentWebview());
749     if (!url) {
750         LogError("url is empty");
751         return;
752     }
753     if (ClientModule::ServiceSupport::launchViewService(
754             elm_win_xwindow_get(m_windowData->getEvasObject(Layer::WINDOW)),
755             url))
756     {
757         LogDebug("success");
758     } else {
759         LogDebug("fail");
760     }
761 }
762
763 void WrtClient::hwkeyCallback(const std::string& key)
764 {
765     if (m_settingList->getBackButtonPresence() == BackButton_Enable
766         || m_currentViewMode == VIEWMODE_TYPE_WINDOWED)
767     {
768         // windowed UX - hosted application
769         if (key == KeyName::BACK) {
770             if (m_isWebkitFullscreen) {
771                 ewk_view_fullscreen_exit(m_widget->GetCurrentWebview());
772             } else {
773                 m_widget->Backward();
774             }
775         } else if (key == KeyName::MENU) {
776             // UX isn't confirmed
777             // m_windowData->showCtxpopup();
778         }
779     } else {
780         // packaged application
781         if (key == KeyName::BACK) {
782             if (m_isFullscreenByPlatform) {
783                 ewk_view_fullscreen_exit(m_widget->GetCurrentWebview());
784             }
785         }
786     }
787 }
788
789 void WrtClient::setLayout(Evas_Object* webview)
790 {
791     LogDebug("add new webkit buffer to window");
792     Assert(webview);
793     m_windowData->setWebview(webview);
794     evas_object_show(webview);
795     evas_object_show(m_windowData->getEvasObject(Layer::WINDOW));
796 }
797
798 void WrtClient::unsetLayout(Evas_Object* webview)
799 {
800     LogDebug("remove current webkit buffer from window");
801     Assert(webview);
802     evas_object_hide(webview);
803     m_windowData->unsetWebview();
804 }
805
806 void WrtClient::shutdownStep()
807 {
808     LogDebug("Closing Wrt connection ...");
809
810     if (m_widget && m_widgetState) {
811         m_widgetState = WidgetState_Stopped;
812         m_widget->Hide();
813         // AutoRotation, focusCallback use m_widget pointer internally.
814         // It must be unset before m_widget is released.
815         m_submodeSupport->deinitialize();
816         unsetWindowOrientation();
817         m_windowData->smartCallbackDel(Layer::FOCUS,
818                                        "focused",
819                                        focusedCallback);
820         m_windowData->smartCallbackDel(Layer::FOCUS,
821                                        "unfocused",
822                                        unfocusedCallback);
823         m_widget.reset();
824         ewk_context_delete(s_preparedEwkContext);
825         WRT::CoreModuleSingleton::Instance().Terminate();
826     }
827     if (m_initialized) {
828         m_initialized = false;
829     }
830     m_windowData.reset();
831     Quit();
832 }
833
834 void WrtClient::autoRotationCallback(void* data, Evas_Object* obj, void* /*event*/)
835 {
836     LogDebug("entered");
837
838     Assert(data);
839     Assert(obj);
840
841     WrtClient* This = static_cast<WrtClient*>(data);
842     This->autoRotationSetOrientation(obj);
843 }
844
845 void WrtClient::focusedCallback(void* data,
846                                 Evas_Object* /*obj*/,
847                                 void* /*eventInfo*/)
848 {
849     LogDebug("entered");
850     Assert(data);
851     WrtClient* This = static_cast<WrtClient*>(data);
852     elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_TRUE);
853 }
854
855 void WrtClient::unfocusedCallback(void* data,
856                                 Evas_Object* /*obj*/,
857                                 void* /*eventInfo*/)
858 {
859     LogDebug("entered");
860     Assert(data);
861     WrtClient* This = static_cast<WrtClient*>(data);
862     elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_FALSE);
863 }
864
865 void WrtClient::autoRotationSetOrientation(Evas_Object* obj)
866 {
867     LogDebug("entered");
868     Assert(obj);
869
870     AutoRotationSupport::setOrientation(obj, m_widget->GetCurrentWebview(),
871                                 (m_splashScreen) ? m_splashScreen.get(): NULL);
872 }
873
874 int WrtClient::languageChangedCallback(void *data)
875 {
876     LogDebug("Language Changed");
877     if (!data) {
878         return 0;
879     }
880     WrtClient* wrtClient = static_cast<WrtClient*>(data);
881     if (!(wrtClient->m_dao)) {
882         return 0;
883     }
884
885     // reset function fetches system locales and recreates language tags
886     LanguageTagsProviderSingleton::Instance().resetLanguageTags();
887     // widget default locales are added to language tags below
888     DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale();
889     if (!defloc.IsNull()) {
890         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
891             *defloc);
892     }
893
894     if (wrtClient->m_launched &&
895         wrtClient->m_widgetState != WidgetState_Stopped)
896     {
897         wrtClient->m_widget->ReloadStartPage();
898     }
899     return 0;
900 }
901
902 void WrtClient::Quit()
903 {
904     ewk_shutdown();
905     DPL::Application::Quit();
906 }
907
908 static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler)
909 {
910     int fd = ecore_main_fd_handler_fd_get(handler);
911
912     if (fd == -1)
913     {
914         LogDebug("ECORE_FD_GET");
915         exit(-1);
916     }
917
918     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
919     {
920         LogDebug("ECORE_FD_ERROR");
921         close(fd);
922         exit(-1);
923     }
924
925     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
926     {
927         LogDebug("ECORE_FD_READ");
928         {
929             app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
930             memset(pkt, 0, AUL_SOCK_MAXBUFF);
931
932             int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
933             close(fd);
934
935             if (recv_ret == -1)
936             {
937                 LogDebug("recv error!");
938                 free(pkt);
939                 exit(-1);
940             }
941
942             LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len);
943             ecore_main_fd_handler_del(handler);
944             process_pool_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv);
945             free(pkt);
946         }
947         ecore_main_loop_quit();
948     }
949
950     return ECORE_CALLBACK_CANCEL;
951 }
952
953 static void vconf_changed_handler(keynode_t* /*key*/, void* /*data*/)
954 {
955     LogDebug("VCONFKEY_LANGSET vconf-key was changed!");
956
957     // When system language is changed, the candidate process will be created again.
958     exit(-1);
959 }
960
961 void set_env()
962 {
963 #ifndef TIZEN_PUBLIC
964     setenv("COREGL_FASTPATH", "1", 1);
965 #endif
966     setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
967     setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
968     setenv("ELM_IMAGE_CACHE", "0", 1);
969 }
970
971 int main(int argc,
972          char *argv[])
973 {
974     // process pool - store arg's value
975     app_argc = argc;
976     app_argv = argv;
977
978 #ifndef X11
979     // Mesa does a bad job detecting the correct EGL
980     // platform to use, and ends up assuming that the
981     // wrt-client is using X
982     setenv("EGL_PLATFORM", "wayland", 1);
983 #endif
984
985     UNHANDLED_EXCEPTION_HANDLER_BEGIN
986     {
987         ADD_PROFILING_POINT("main-entered", "point");
988
989         // Set log tagging
990         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
991
992         // Set environment variables
993         set_env();
994
995         if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d"))
996         {
997             LogDebug("Entered dummy process mode");
998             sprintf(argv[0], "%s                                              ",
999                     DUMMY_PROCESS_PATH);
1000
1001             // Set 'root' home directory
1002             setenv(HOME, ROOT_HOME_PATH, 1);
1003
1004             LogDebug("Prepare ewk_context");
1005             appcore_set_i18n("wrt-client", NULL);
1006             ewk_set_arguments(argc, argv);
1007             setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
1008             s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
1009
1010             if (s_preparedEwkContext == NULL)
1011             {
1012                 LogDebug("Creating webkit context was failed!");
1013                 exit(-1);
1014             }
1015
1016             int client_fd = __connect_process_pool_server();
1017
1018             if (client_fd == -1)
1019             {
1020                 LogDebug("Connecting process_pool_server was failed!");
1021                 exit(-1);
1022             }
1023
1024             // register language changed callback
1025             vconf_notify_key_changed(VCONFKEY_LANGSET, vconf_changed_handler, NULL);
1026
1027             LogDebug("Prepare window_data");
1028             // Temporarily change HOME path to app
1029             // This change is needed for getting elementary profile
1030             // /opt/home/app/.elementary/config/mobile/base.cfg
1031             const char* backupEnv = getenv(HOME);
1032             setenv(HOME, APP_HOME_PATH, 1);
1033             LogDebug("elm_init()");
1034             elm_init(argc, argv);
1035             setenv(HOME, backupEnv, 1);
1036
1037             LogDebug("WindowData()");
1038             s_preparedWindowData = new WindowData(static_cast<unsigned long>(getpid()));
1039
1040             Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd,
1041                                            (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR),
1042                                            proces_pool_fd_handler, NULL, NULL, NULL);
1043
1044             if (fd_handler == NULL)
1045             {
1046                 LogDebug("fd_handler is NULL");
1047                 exit(-1);
1048             }
1049
1050             setpriority(PRIO_PROCESS, 0, 0);
1051
1052             LogDebug("ecore_main_loop_begin()");
1053             ecore_main_loop_begin();
1054             LogDebug("ecore_main_loop_begin()_end");
1055
1056             // deregister language changed callback
1057             vconf_ignore_key_changed(VCONFKEY_LANGSET, vconf_changed_handler);
1058
1059             std::string tizenId =
1060                 ClientModule::CommandLineParser::getTizenId(argc, argv);
1061             ewk_context_message_post_to_injected_bundle(
1062                 s_preparedEwkContext,
1063                 MESSAGE_NAME_INITIALIZE,
1064                 tizenId.c_str());
1065
1066         }
1067         else
1068         {
1069             // This code is to fork a web process without exec.
1070             std::string tizenId =
1071                 ClientModule::CommandLineParser::getTizenId(argc, argv);
1072
1073             if (!tizenId.empty()) {
1074                 if (UID_ROOT == getuid()) {
1075                     // Drop root permission
1076                     // Only launch web application by console command case has root permission
1077                     if (!ClientModule::SecuritySupport::setAppPrivilege(tizenId)) {
1078                         LogError("Fail to set app privilege : [" << tizenId << "]");
1079                         exit(-1);
1080                     }
1081                 }
1082
1083                 LogDebug("Launching by fork mode");
1084                 // Language env setup
1085                 appcore_set_i18n("wrt-client", NULL);
1086                 ewk_set_arguments(argc, argv);
1087                 setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
1088                 s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
1089                         BUNDLE_PATH);
1090
1091                 if (s_preparedEwkContext == NULL)
1092                 {
1093                     LogDebug("Creating webkit context was failed!");
1094                     Wrt::Popup::PopupInvoker().showInfo("Error", "Creating webkit context was failed.", "OK");
1095                     exit(-1);
1096                 }
1097
1098                 // plugin init
1099                 ewk_context_message_post_to_injected_bundle(
1100                     s_preparedEwkContext,
1101                     MESSAGE_NAME_INITIALIZE,
1102                     tizenId.c_str());
1103             }
1104         }
1105
1106         // Output on stdout will be flushed after every newline character,
1107         // even if it is redirected to a pipe. This is useful for running
1108         // from a script and parsing output.
1109         // (Standard behavior of stdlib is to use full buffering when
1110         // redirected to a pipe, which means even after an end of line
1111         // the output may not be flushed).
1112         setlinebuf(stdout);
1113
1114         WrtClient app(app_argc, app_argv);
1115
1116         ADD_PROFILING_POINT("Before appExec", "point");
1117         int ret = app.Exec();
1118         LogDebug("App returned: " << ret);
1119         ret = app.getReturnStatus();
1120         LogDebug("WrtClient returned: " << ret);
1121         return ret;
1122     }
1123     UNHANDLED_EXCEPTION_HANDLER_END
1124 }