[Release] wrt_0.8.235
[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     // temporary solution because we have no way to get ewk_context from runnable object.
659     if (s_preparedEwkContext)
660     {
661         ewk_context_cache_clear(s_preparedEwkContext);
662         ewk_context_notify_low_memory(s_preparedEwkContext);
663     }
664
665     return 0;
666 }
667
668 void WrtClient::setInitialViewMode(void)
669 {
670     Assert(m_dao);
671     WrtDB::WindowModeList windowModes = m_dao->getWindowModes();
672     FOREACH(it, windowModes) {
673         std::string viewMode = DPL::ToUTF8String(*it);
674         switch(viewMode[0]) {
675             case 'f':
676                 if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
677                     m_initialViewMode = viewMode;
678                     m_currentViewMode = m_initialViewMode;
679                     break;
680                 }
681                 break;
682             case 'm':
683                 if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
684                     m_initialViewMode = viewMode;
685                     m_currentViewMode = m_initialViewMode;
686                     break;
687                 }
688                 break;
689             case 'w':
690                 if (viewMode == VIEWMODE_TYPE_WINDOWED) {
691                     m_initialViewMode = viewMode;
692                     m_currentViewMode = m_initialViewMode;
693                     break;
694                 }
695                 break;
696             default:
697                 break;
698         }
699     }
700 }
701
702 void WrtClient::setWindowInitialOrientation(void)
703 {
704     Assert(m_windowData);
705     Assert(m_dao);
706
707     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
708     if (rotationValue == Screen_Portrait) {
709         setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY);
710     } else if (rotationValue == Screen_Landscape) {
711         setWindowOrientation(OrientationAngle::Window::Landscape::PRIMARY);
712     } else if (rotationValue == Screen_AutoRotation) {
713         if (!AutoRotationSupport::setAutoRotation(m_windowData->m_win,
714                                                   autoRotationCallback,
715                                                   this))
716         {
717             LogError("Fail to set auto rotation");
718         }
719     } else {
720         setWindowOrientation(OrientationAngle::Window::Portrait::PRIMARY);
721     }
722 }
723
724 void WrtClient::setWindowOrientation(int angle)
725 {
726     Assert(m_windowData);
727     m_windowData->setOrientation(angle);
728 }
729
730 void WrtClient::unsetWindowOrientation(void)
731 {
732     Assert(m_windowData);
733     Assert(m_dao);
734
735     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
736     if (rotationValue == Screen_AutoRotation) {
737         AutoRotationSupport::unsetAutoRotation(m_windowData->m_win, autoRotationCallback);
738     }
739 }
740
741 void WrtClient::setEwkInitialOrientation(void)
742 {
743     Assert(m_widget);
744     Assert(m_dao);
745
746     WidgetSettingScreenLock rotationValue = m_settingList->getRotationValue();
747     if (rotationValue == Screen_Portrait) {
748         ewk_view_orientation_send(
749             m_widget->GetCurrentWebview(),
750              OrientationAngle::W3C::Portrait::PRIMARY);
751     } else if (rotationValue == Screen_Landscape) {
752         ewk_view_orientation_send(
753             m_widget->GetCurrentWebview(),
754             OrientationAngle::W3C::Landscape::PRIMARY);
755     } else if (rotationValue == Screen_AutoRotation) {
756          ewk_view_orientation_send(
757             m_widget->GetCurrentWebview(),
758             OrientationAngle::W3C::Portrait::PRIMARY);
759     } else {
760         ewk_view_orientation_send(
761             m_widget->GetCurrentWebview(),
762             OrientationAngle::W3C::Portrait::PRIMARY);
763     }
764 }
765
766 void WrtClient::setCtxpopupItem(void)
767 {
768     WindowData::CtxpopupItemDataList data;
769
770     // 1. share
771     WindowData::CtxpopupCallbackType shareCallback =
772         DPL::MakeDelegate(this, &WrtClient::ctxpopupShare);
773     WindowData::CtxpopupItemData shareData("Share",
774                                            std::string(),
775                                            shareCallback);
776
777     // 2. reload
778     WindowData::CtxpopupCallbackType reloadCallback =
779         DPL::MakeDelegate(this, &WrtClient::ctxpopupReload);
780     WindowData::CtxpopupItemData reloadData("Reload",
781                                             std::string(),
782                                             reloadCallback);
783
784     // 3. Open in browser
785     WindowData::CtxpopupCallbackType launchBrowserCallback =
786         DPL::MakeDelegate(this, &WrtClient::ctxpopupLaunchBrowser);
787     WindowData::CtxpopupItemData launchBrowserData("Open in browser",
788                                                    std::string(),
789                                                    launchBrowserCallback);
790     data.push_back(shareData);
791     data.push_back(reloadData);
792     data.push_back(launchBrowserData);
793     m_windowData->setCtxpopupItemData(data);
794 }
795
796 void WrtClient::ctxpopupShare(void)
797 {
798     LogDebug("share");
799     const char* url = ewk_view_url_get(m_widget->GetCurrentWebview());
800     if (!url) {
801         LogError("url is empty");
802         return;
803     }
804     if (ClientModule::ServiceSupport::launchShareService(
805             elm_win_xwindow_get(m_windowData->m_win),
806             url))
807     {
808         LogInfo("success");
809     } else {
810         LogInfo("fail");
811     }
812 }
813
814 void WrtClient::ctxpopupReload(void)
815 {
816     LogDebug("reload");
817     ewk_view_reload(m_widget->GetCurrentWebview());
818 }
819
820 void WrtClient::ctxpopupLaunchBrowser(void)
821 {
822     LogDebug("launchBrowser");
823     const char* url = ewk_view_url_get(m_widget->GetCurrentWebview());
824     if (!url) {
825         LogError("url is empty");
826         return;
827     }
828     if (ClientModule::ServiceSupport::launchViewService(
829             elm_win_xwindow_get(m_windowData->m_win),
830             url))
831     {
832         LogInfo("success");
833     } else {
834         LogInfo("fail");
835     }
836 }
837
838 void WrtClient::hwkeyCallback(const std::string& key)
839 {
840     if (m_settingList->getBackButtonPresence() == BackButton_Enable
841         || m_currentViewMode == VIEWMODE_TYPE_WINDOWED)
842     {
843         if (key == KeyName::BACK) {
844             m_widget->Backward();
845         } else if (key == KeyName::MENU) {
846             // UX isn't confirmed
847             // m_windowData->showCtxpopup();
848         }
849     }
850 }
851
852 void WrtClient::setLayout(Evas_Object* newBuffer)
853 {
854     LogDebug("add new webkit buffer to window");
855     Assert(newBuffer);
856     m_windowData->setEvasObjectForLayout(newBuffer);
857     evas_object_show(newBuffer);
858     evas_object_show(m_windowData->m_win);
859 }
860
861 void WrtClient::unsetLayout(Evas_Object* currentBuffer)
862 {
863     LogDebug("remove current webkit buffer from window");
864     Assert(currentBuffer);
865     evas_object_hide(currentBuffer);
866     m_windowData->unsetEvasObjectForLayout();
867 }
868
869 void WrtClient::shutdownStep()
870 {
871     LogDebug("Closing Wrt connection ...");
872
873     if (m_widget && m_widgetState) {
874         m_widgetState = WidgetState_Stopped;
875         m_widget->Hide();
876         // AutoRotation, focusCallback use m_widget pointer internally.
877         // It must be unset before m_widget is released.
878         unsetWindowOrientation();
879         m_windowData->focusCallbackDel("focused", focusedCallback);
880         m_windowData->focusCallbackDel("unfocused", unfocusedCallback);
881         m_widget.reset();
882         ewk_context_delete(s_preparedEwkContext);
883         PrepareExternalStorageSingleton::Instance().Deinitialize();
884         WRT::CoreModuleSingleton::Instance().Terminate();
885     }
886     if (m_initialized) {
887         m_initialized = false;
888     }
889     m_windowData.reset();
890     Quit();
891 }
892
893 void WrtClient::autoRotationCallback(void* data, Evas_Object* obj, void* /*event*/)
894 {
895     LogInfo("entered");
896
897     Assert(data);
898     Assert(obj);
899
900     WrtClient* This = static_cast<WrtClient*>(data);
901
902     This->autoRotationSetOrientation(obj);
903 }
904
905 void WrtClient::focusedCallback(void* data,
906                                 Evas_Object* /*obj*/,
907                                 void* /*eventInfo*/)
908 {
909     LogInfo("entered");
910     Assert(data);
911     WrtClient* This = static_cast<WrtClient*>(data);
912     elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_TRUE);
913 }
914
915 void WrtClient::unfocusedCallback(void* data,
916                                 Evas_Object* /*obj*/,
917                                 void* /*eventInfo*/)
918 {
919     LogInfo("entered");
920     Assert(data);
921     WrtClient* This = static_cast<WrtClient*>(data);
922     elm_object_focus_set(This->m_widget->GetCurrentWebview(), EINA_FALSE);
923 }
924
925 void WrtClient::autoRotationSetOrientation(Evas_Object* obj)
926 {
927     LogInfo("entered");
928     Assert(obj);
929
930     AutoRotationSupport::setOrientation(obj, m_widget->GetCurrentWebview(),
931                                 (m_splashScreen) ? m_splashScreen.get(): NULL);
932 }
933
934 int WrtClient::languageChangedCallback(void *data)
935 {
936     LogDebug("Language Changed");
937     if (!data) {
938         return 0;
939     }
940     WrtClient* wrtClient = static_cast<WrtClient*>(data);
941     if (!(wrtClient->m_dao)) {
942         return 0;
943     }
944
945     // reset function fetches system locales and recreates language tags
946     LanguageTagsProviderSingleton::Instance().resetLanguageTags();
947     // widget default locales are added to language tags below
948     DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale();
949     if (!defloc.IsNull()) {
950         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
951             *defloc);
952     }
953
954     if (wrtClient->m_launched &&
955         wrtClient->m_widgetState != WidgetState_Stopped)
956     {
957         wrtClient->m_widget->ReloadStartPage();
958     }
959     return 0;
960 }
961
962 void WrtClient::Quit()
963 {
964     ewk_shutdown();
965     DPL::Application::Quit();
966 }
967
968 static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler)
969 {
970     int fd = ecore_main_fd_handler_fd_get(handler);
971
972     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
973     {
974         LogDebug("ECORE_FD_ERROR");
975
976         if (fd != -1)
977         {
978             close(fd);
979         }
980
981         exit(-1);
982         return ECORE_CALLBACK_CANCEL;
983     }
984
985     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
986     {
987         LogDebug("ECORE_FD_READ");
988         {
989             app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
990             memset(pkt, 0, AUL_SOCK_MAXBUFF);
991
992             int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
993
994             if (fd != -1)
995             {
996                 close(fd);
997             }
998
999             if (recv_ret == -1)
1000             {
1001                 LogDebug("recv error!");
1002                 exit(-1);
1003             }
1004             LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len);
1005
1006             ecore_main_fd_handler_del(handler);
1007
1008             process_pool_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv);
1009
1010             free(pkt);
1011         }
1012
1013         ecore_main_loop_quit();
1014         return ECORE_CALLBACK_CANCEL;
1015     }
1016
1017     return ECORE_CALLBACK_CANCEL;
1018 }
1019
1020 static void vconf_changed_handler(keynode_t* /*key*/, void* /*data*/)
1021 {
1022     LogInfo("VCONFKEY_LANGSET vconf-key was changed!");
1023
1024     // When system language is changed, the candidate process will be created again.
1025     exit(-1);
1026 }
1027
1028 void set_env()
1029 {
1030     // set evas backend type
1031     if (!getenv("ELM_ENGINE"))
1032     {
1033         if (!setenv("ELM_ENGINE", "gl", 1))
1034         {
1035             LogDebug("Enable backend");
1036         }
1037     }
1038     else
1039     {
1040         LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
1041     }
1042
1043 #ifndef TIZEN_PUBLIC
1044     setenv("COREGL_FASTPATH", "1", 1);
1045 #endif
1046     setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
1047     setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
1048     setenv("ELM_IMAGE_CACHE", "0", 1);
1049 }
1050
1051 int main(int argc,
1052          char *argv[])
1053 {
1054     // process pool - store arg's value
1055     app_argc = argc;
1056     app_argv = argv;
1057
1058     UNHANDLED_EXCEPTION_HANDLER_BEGIN
1059     {
1060         ADD_PROFILING_POINT("main-entered", "point");
1061
1062         // Set log tagging
1063         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
1064
1065         // Set environment variables
1066         set_env();
1067
1068         if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d"))
1069         {
1070             LogInfo("Entered dummy process mode");
1071             sprintf(argv[0], "%s                                              ",
1072                     DUMMY_PROCESS_PATH);
1073
1074             // Set 'root' home directory
1075             setenv(HOME, ROOT_HOME_PATH, 1);
1076
1077             LogInfo("Prepare ewk_context");
1078             appcore_set_i18n("wrt-client", NULL);
1079             ewk_set_arguments(argc, argv);
1080             setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
1081             s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
1082
1083             if (s_preparedEwkContext == NULL)
1084             {
1085                 LogInfo("Creating webkit context was failed!");
1086                 exit(-1);
1087             }
1088
1089             int client_fd = __connect_process_pool_server();
1090
1091             if (client_fd == -1)
1092             {
1093                 LogInfo("Connecting process_pool_server was failed!");
1094                 exit(-1);
1095             }
1096
1097             // register language changed callback
1098             vconf_notify_key_changed(VCONFKEY_LANGSET, vconf_changed_handler, NULL);
1099
1100             LogInfo("Prepare window_data");
1101             // Temporarily change HOME path to app
1102             // This change is needed for getting elementary profile
1103             // /opt/home/app/.elementary/config/mobile/base.cfg
1104             const char* backupEnv = getenv(HOME);
1105             setenv(HOME, APP_HOME_PATH, 1);
1106             LogInfo("elm_init()");
1107             elm_init(argc, argv);
1108             setenv(HOME, backupEnv, 1);
1109
1110             LogInfo("WindowData()");
1111             s_preparedWindowData = new WindowData(static_cast<unsigned long>(getpid()));
1112
1113             Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd,
1114                                            (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR),
1115                                            proces_pool_fd_handler, NULL, NULL, NULL);
1116
1117             if (fd_handler == NULL)
1118             {
1119                 LogInfo("fd_handler is NULL");
1120                 exit(-1);
1121             }
1122
1123             setpriority(PRIO_PROCESS, 0, 0);
1124
1125             LogDebug("ecore_main_loop_begin()");
1126             ecore_main_loop_begin();
1127             LogDebug("ecore_main_loop_begin()_end");
1128
1129             // deregister language changed callback
1130             vconf_ignore_key_changed(VCONFKEY_LANGSET, vconf_changed_handler);
1131
1132             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
1133             ewk_context_message_post_to_injected_bundle(
1134                 s_preparedEwkContext,
1135                 MESSAGE_NAME_INITIALIZE,
1136                 tizenId.c_str());
1137
1138         }
1139         else
1140         {
1141             // This code is to fork a web process without exec.
1142             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
1143             if (!tizenId.empty()) {
1144                 std::size_t pos =
1145                     tizenId.find(WrtDB::AppControlPrefix::PROCESS_PREFIX);
1146                 if (pos != std::string::npos) {
1147                     tizenId.erase(pos);
1148                 }
1149
1150                 LogDebug("Launching by fork mode");
1151                 // Language env setup
1152                 appcore_set_i18n("wrt-client", NULL);
1153                 ewk_set_arguments(argc, argv);
1154                 setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
1155                 s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
1156                         BUNDLE_PATH);
1157
1158                 if (s_preparedEwkContext == NULL)
1159                 {
1160                     LogInfo("Creating webkit context was failed!");
1161                     Wrt::Popup::PopupInvoker().showInfo("Error", "Creating webkit context was failed.", "OK");
1162                     exit(-1);
1163                 }
1164
1165                 // plugin init
1166                 ewk_context_message_post_to_injected_bundle(
1167                     s_preparedEwkContext,
1168                     MESSAGE_NAME_INITIALIZE,
1169                     tizenId.c_str());
1170             }
1171         }
1172
1173         // Output on stdout will be flushed after every newline character,
1174         // even if it is redirected to a pipe. This is useful for running
1175         // from a script and parsing output.
1176         // (Standard behavior of stdlib is to use full buffering when
1177         // redirected to a pipe, which means even after an end of line
1178         // the output may not be flushed).
1179         setlinebuf(stdout);
1180
1181         WrtClient app(app_argc, app_argv);
1182
1183         ADD_PROFILING_POINT("Before appExec", "point");
1184         int ret = app.Exec();
1185         LogDebug("App returned: " << ret);
1186         ret = app.getReturnStatus();
1187         LogDebug("WrtClient returned: " << ret);
1188         return ret;
1189     }
1190     UNHANDLED_EXCEPTION_HANDLER_END
1191 }