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