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