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