[Release] wrt_0.8.185
[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 "webkit/bundles/plugin_module_support.h"
36 #include <popup-runner/PopupInvoker.h>
37 #include <prepare_external_storage.h>
38 #include <vconf.h>
39
40 #include "process_pool.h"
41 #include "menu_db_util.h"
42 #include "launchpad_util.h"
43
44 //W3C PACKAGING enviroment variable name
45 #define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
46
47 // window signal callback
48 const char *EDJE_SHOW_BACKWARD_SIGNAL = "show,backward,signal";
49 const std::string VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
50 const std::string VIEWMODE_TYPE_MAXIMIZED = "maximized";
51 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
52 const char* const BUNDLE_PATH = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
53 const char* const caCertPath = "/opt/usr/share/certs/ca-certificate.crt";
54
55 // process pool
56 const char* const DUMMY_PROCESS_PATH = "/usr/bin/wrt_launchpad_daemon_candidate";
57 static Ewk_Context* s_preparedEwkContext = NULL;
58 static WindowData*  s_preparedWindowData = NULL;
59 static int    app_argc = 0;
60 static char** app_argv = NULL;
61
62 // orientation
63 const int WIN_ORIENTATION_PORTRAIT_PRIMARY_ANGLE = 0;
64 const int WIN_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE = 270;
65 const int W3C_ORIENTATION_PORTRAIT_PRIMARY_ANGLE = 0;
66 const int W3C_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE = 90;
67
68 // env
69 const char* const HOME = "HOME";
70 const char* const APP_HOME_PATH = "/opt/home/app";
71
72 WrtClient::WrtClient(int argc, char **argv) :
73     Application(argc, argv, "wrt-client", false),
74     DPL::TaskDecl<WrtClient>(this),
75     m_launched(false),
76     m_initializing(false),
77     m_initialized(false),
78     m_sdkLauncherPid(0),
79     m_debugMode(false),
80     m_debuggerPort(0),
81     m_returnStatus(ReturnStatus::Succeeded),
82     m_widgetState(WidgetState::WidgetState_Stopped)
83 {
84     Touch();
85     LogDebug("App Created");
86 }
87
88 WrtClient::~WrtClient()
89 {
90     LogDebug("App Finished");
91 }
92
93 WrtClient::ReturnStatus::Type WrtClient::getReturnStatus() const
94 {
95     return m_returnStatus;
96 }
97
98 void WrtClient::OnStop()
99 {
100     LogInfo("Stopping Dummy Client");
101 }
102
103 void WrtClient::OnCreate()
104 {
105     LogInfo("On Create");
106     ADD_PROFILING_POINT("OnCreate callback", "point");
107     ewk_init();
108 }
109
110 void WrtClient::OnResume()
111 {
112     if (m_widgetState != WidgetState_Suspended) {
113         LogWarning("Widget is not suspended, resuming was skipped");
114         return;
115     }
116     m_widget->Resume();
117     m_widgetState = WidgetState_Running;
118 }
119
120 void WrtClient::OnPause()
121 {
122     if (m_widgetState != WidgetState_Running) {
123         LogWarning("Widget is not running to be suspended");
124         return;
125     }
126     m_widget->Suspend();
127     m_widgetState = WidgetState_Suspended;
128 }
129
130 void WrtClient::OnReset(bundle *b)
131 {
132     LogDebug("OnReset");
133     // bundle argument is freed after OnReset() is returned
134     // So bundle duplication is needed
135     ApplicationDataSingleton::Instance().setBundle(bundle_dup(b));
136
137     if (true == m_initializing) {
138         LogDebug("can not handle reset event");
139         return;
140     }
141     if (true == m_launched) {
142         if (m_widgetState == WidgetState_Stopped) {
143             LogError("Widget is not running to be reset");
144             return;
145         }
146         m_widget->Reset();
147         m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
148         m_widgetState = WidgetState_Running;
149     } else {
150         if (true == checkArgument()) {
151             setStep();
152         } else {
153             showHelpAndQuit();
154         }
155     }
156
157     // low memory callback set
158     appcore_set_event_callback(
159             APPCORE_EVENT_LOW_MEMORY,
160             WrtClient::appcoreLowMemoryCallback,
161             this);
162 }
163
164 void WrtClient::OnTerminate()
165 {
166     LogDebug("Wrt Shutdown now");
167     shutdownStep();
168 }
169
170 void WrtClient::showHelpAndQuit()
171 {
172     printf("Usage: wrt-client [OPTION]... [WIDGET: ID]...\n"
173            "launch widgets.\n"
174            "Mandatory arguments to long options are mandatory for short "
175            "options too.\n"
176            "  -h,    --help                                 show this help\n"
177            "  -l,    --launch                               "
178            "launch widget with given tizen ID\n"
179            "  -t,    --tizen                                "
180            "launch widget with given tizen ID\n"
181            "\n");
182
183     Quit();
184 }
185
186 bool WrtClient::checkArgument()
187 {
188     std::string tizenId = getTizenIdFromArgument(m_argc, m_argv);
189
190     if (tizenId.empty()) {
191         // Just show help
192         return false;
193     } else {
194 #ifdef MULTIPROCESS_SERVICE_SUPPORT
195         const char * SERVICE_POSTFIX = "-__SERVICE_PROCESS__";
196         std::size_t pos = tizenId.find(SERVICE_POSTFIX);
197         if (pos != std::string::npos) {
198             std::string id = tizenId.substr(pos);
199             id.erase(strlen(SERVICE_POSTFIX));
200             std::stringstream s(id);
201             unsigned serviceIndex;
202             s >> serviceIndex;
203             m_serviceIndex = serviceIndex;
204             tizenId.erase(pos);
205             LogDebug("service index " << serviceIndex);
206         }
207 #endif
208         m_tizenId = tizenId;
209         LogDebug("Tizen id: " << m_tizenId);
210         return true;
211     }
212 }
213
214 std::string WrtClient::getTizenIdFromArgument(int argc, char **argv)
215 {
216     LogInfo("checkArgument");
217     std::string arg = argv[0];
218
219     if (arg.empty()) {
220         return "";
221     }
222
223     if (arg.find("wrt-client") != std::string::npos) {
224         if (argc <= 1) {
225             return "";
226         }
227
228         arg = argv[1];
229
230         if (arg == "-h" || arg == "--help") {
231             return "";
232         } else if (arg == "-l" || arg == "--launch" ||
233                    arg == "-t" || arg == "--tizen")
234         {
235             if (argc != 3) {
236                 return "";
237             }
238             return argv[2];
239         } else {
240             return "";
241         }
242     } else {
243         // Launch widget based on application basename
244         size_t pos = arg.find_last_of('/');
245
246         if (pos != std::string::npos) {
247             arg = arg.erase(0, pos + 1);
248         }
249
250         return arg;
251     }
252 }
253
254 void WrtClient::setStep()
255 {
256     LogInfo("setStep");
257
258     AddStep(&WrtClient::initStep);
259
260     setSdkLauncherDebugData();
261
262     AddStep(&WrtClient::launchStep);
263     AddStep(&WrtClient::shutdownStep);
264
265     m_initializing = true;
266
267     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(NextStepEvent());
268 }
269
270 void WrtClient::setSdkLauncherDebugData()
271 {
272     LogDebug("setSdkLauncherDebugData");
273
274     /* check bundle from sdk launcher */
275     bundle *bundleFromSdkLauncher;
276     bundleFromSdkLauncher = bundle_import_from_argv(m_argc, m_argv);
277     const char *bundle_debug = bundle_get_val(bundleFromSdkLauncher, "debug");
278     const char *bundle_pid = bundle_get_val(bundleFromSdkLauncher, "pid");
279     if (bundle_debug != NULL && bundle_pid != NULL) {
280         if (strcmp(bundle_debug, "true") == 0) {
281             m_debugMode = true;
282             m_sdkLauncherPid = atoi(bundle_pid);
283         } else {
284             m_debugMode = false;
285         }
286     }
287     bundle_free(bundleFromSdkLauncher);
288 }
289
290 bool WrtClient::checkDebugMode(SDKDebugData* debugData)
291 {
292     LogError("Checking for debug mode");
293     Assert(m_dao);
294
295     bool debugMode = debugData->debugMode;
296
297     LogInfo("[DEBUG_MODE] Widget is launched in " <<
298             (debugMode ? "DEBUG" : "RETAIL") <<
299             " mode.");
300
301     if (debugMode == true) {
302         // In WAC widget, only test widgets can use web inspector.
303         // In TIZEN widget,
304         // every launched widgets as debug mode can use it.
305         if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_WAC20) {
306             bool developerMode =
307                 WRT::CoreModuleSingleton::Instance().developerMode();
308             //This code will be activated
309             //after WAC test certificate is used by SDK
310             //bool isTestWidget = view->m_widgetModel->IsTestWidget.Get();
311             //if(!isTestWidget)
312             //{
313             //    LogInfo("This is not WAC Test Widget");
314             //    break;
315             //}
316             if (!developerMode) {
317                 LogInfo("This is not WAC Developer Mode");
318                 debugMode = false;
319             }
320         }
321     }
322     return debugMode;
323 }
324
325 void WrtClient::OnEventReceived(const NextStepEvent& /*event*/)
326 {
327     LogDebug("Executing next step");
328     NextStep();
329 }
330
331 void WrtClient::initStep()
332 {
333     LogDebug("");
334     if (WRT::CoreModuleSingleton::Instance().Init()) {
335         m_initialized = true;
336     } else {
337         m_returnStatus = ReturnStatus::Failed;
338         SwitchToStep(&WrtClient::shutdownStep);
339     }
340
341     // ecore_event_jobs are processed sequentially without concession to
342     // other type events. To give a chance of execute to other events,
343     // ecore_timer_add was used.
344     DPL::Event::ControllerEventHandler<NextStepEvent>::PostTimedEvent(
345         NextStepEvent(), 0.001);
346 }
347
348 bool WrtClient::checkWACTestCertififedWidget()
349 {
350     // WAC Waikiki Beta Release Core Specification: Widget Runtime
351     // 10 Dec 2010
352     //
353     // WR-4710 The WRT MUST enable debug functions only for WAC test widgets
354     // i.e. the functions must not be usable for normal WAC widgets, even when
355     // a WAC test widget is executing.
356     ADD_PROFILING_POINT("DeveloperModeCheck", "start");
357     Assert(!!m_dao);
358     // WAC test widget
359     // A widget signed with a WAC-issued test certificate as described in
360     // Developer Mode.
361
362     bool developerWidget = m_dao->isTestWidget();
363     bool developerMode = WRT::CoreModuleSingleton::Instance().developerMode();
364
365     LogDebug("Is WAC test widget: " << developerWidget);
366     LogDebug("Is developer Mode: " << developerMode);
367
368     if (developerWidget) {
369         if (!developerMode) {
370             LogError("WAC test certified developer widget is needed for " <<
371                      "developer mode");
372             return false;
373         } else {
374             //TODO: WR-4660 (show popup about developer widget
375             //      during launch
376             LogInfo("POPUP: THIS IS TEST WIDGET!");
377         }
378     }
379     ADD_PROFILING_POINT("DeveloperModeCheck", "stop");
380     return true;
381 }
382
383 void WrtClient::loadFinishCallback(Evas_Object* webview)
384 {
385     ADD_PROFILING_POINT("loadFinishCallback", "start");
386     SDKDebugData* debug = new SDKDebugData;
387     debug->debugMode = m_debugMode;
388     debug->pid = new unsigned long(getpid());
389
390     LogInfo("Post result of launch");
391
392     // Start inspector server, if current mode is debugger mode.
393     // In the WK2 case, ewk_view_inspector_server_start should
394     // be called after WebProcess is created.
395     if (checkDebugMode(debug)) {
396         debug->portnum =
397             ewk_view_inspector_server_start(m_widget->GetCurrentWebview(), 0);
398         if (debug->portnum == 0) {
399             LogWarning("Failed to get portnum");
400         } else {
401             LogInfo("Assigned port number for inspector : "
402                     << debug->portnum);
403         }
404     } else {
405         LogDebug("Debug mode is disabled");
406     }
407
408     //w3c packaging test debug (message on 4>)
409     const char * makeScreen = getenv(W3C_DEBUG_ENV_VARIABLE);
410     if (makeScreen != NULL && strcmp(makeScreen, "1") == 0) {
411         FILE* doutput = fdopen(4, "w");
412         fprintf(doutput, "didFinishLoadForFrameCallback: ready\n");
413         fclose(doutput);
414     }
415
416     if (webview) {
417         LogDebug("Launch succesfull");
418
419         m_launched = true;
420         m_initializing = false;
421         setlinebuf(stdout);
422         ADD_PROFILING_POINT("loadFinishCallback", "stop");
423         printf("launched\n");
424         fflush(stdout);
425     } else {
426         printf("failed\n");
427
428         m_returnStatus = ReturnStatus::Failed;
429         //shutdownStep
430         DPL::Event::ControllerEventHandler<NextStepEvent>::
431             PostEvent(NextStepEvent());
432     }
433
434     if (debug->debugMode) {
435         LogDebug("Send RT signal to wrt-launcher(pid: " << m_sdkLauncherPid);
436         union sigval sv;
437         /* send real time signal with result to wrt-launcher */
438         if (webview) {
439             LogDebug("userData->portnum : " << debug->portnum);
440             sv.sival_int = debug->portnum;
441         } else {
442             sv.sival_int = -1;
443         }
444         sigqueue(m_sdkLauncherPid, SIGRTMIN, sv);
445     }
446
447     ApplicationDataSingleton::Instance().freeBundle();
448
449     LogDebug("Cleaning wrtClient launch resources...");
450     delete debug->pid;
451     delete debug;
452 }
453
454 void WrtClient::progressFinishCallback()
455 {
456     m_splashScreen->stopSplashScreen();
457 }
458
459 void WrtClient::webkitExitCallback()
460 {
461     LogDebug("window close called, terminating app");
462     SwitchToStep(&WrtClient::shutdownStep);
463     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
464         NextStepEvent());
465 }
466
467 void WrtClient::webCrashCallback()
468 {
469     LogError("webProcess crashed");
470     SwitchToStep(&WrtClient::shutdownStep);
471     DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
472         NextStepEvent());
473 }
474
475 void WrtClient::launchStep()
476 {
477     ADD_PROFILING_POINT("launchStep", "start");
478     LogDebug("Launching widget ...");
479
480     ADD_PROFILING_POINT("getRunnableWidgetObject", "start");
481 #ifdef MULTIPROCESS_SERVICE_SUPPORT
482     m_widget = WRT::CoreModuleSingleton::Instance()
483             .getRunnableWidgetObject(m_tizenId, m_serviceIndex);
484 #else
485     m_widget = WRT::CoreModuleSingleton::Instance()
486         .getRunnableWidgetObject(m_tizenId);
487 #endif
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     DPL::Optional<DPL::String> defloc = m_dao->getDefaultlocale();
513     if (!defloc.IsNull()) {
514         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
515             *defloc);
516     }
517
518     PrepareExternalStorageSingleton::Instance().Initialize(m_dao->getTizenPkgId());
519
520     /* remove language change callback */
521     /*
522     LocalizationSetting::SetLanguageChangedCallback(
523             languageChangedCallback, this);
524     */
525
526     ADD_PROFILING_POINT("CreateWindow", "start");
527     if (s_preparedWindowData == NULL) {
528         m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid()), true));
529     } else {
530         m_windowData.reset(s_preparedWindowData);
531         s_preparedWindowData = NULL;
532     }
533     ADD_PROFILING_POINT("CreateWindow", "stop");
534     evas_object_show(m_windowData->m_win);
535     // rotate window to initial value
536     setOrientationWindow();
537
538     WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
539     ADD_PROFILING_POINT("Create splash screen", "start");
540     m_splashScreen.reset(
541         new SplashScreenSupport(m_windowData->m_win));
542     if (m_splashScreen->createSplashScreen(m_dao->getSplashImgSrc())) {
543         m_splashScreen->startSplashScreen();
544         cbs->progressFinish = DPL::MakeDelegate(
545                 this,
546                 &WrtClient::
547                     progressFinishCallback);
548     }
549     ADD_PROFILING_POINT("Create splash screen", "stop");
550     DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao);
551     if (!m_widget->PrepareView(DPL::ToUTF8String(*startUrl),
552             m_windowData->m_win, s_preparedEwkContext))
553     {
554         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
555             NextStepEvent());
556         return;
557     }
558     // send rotate information to ewk
559     setOrientationEwk();
560
561     //you can't show window with splash screen before PrepareView
562     //ewk_view_add_with_context() in viewLogic breaks window
563
564     m_windowData->init();
565
566     WrtDB::WidgetLocalizedInfo localizedInfo =
567         W3CFileLocalization::getLocalizedInfo(m_dao);
568     std::string name = "";
569     if (!(localizedInfo.name.IsNull())) {
570         name = DPL::ToUTF8String(*(localizedInfo.name));
571     }
572     elm_win_title_set(m_windowData->m_win, name.c_str());
573
574     initializeWindowModes();
575     connectElmCallback();
576
577     if (!checkWACTestCertififedWidget()) {
578         LogWarning("WAC Certificate failed, stop launchStep");
579         return;
580     }
581
582     m_widgetState = WidgetState_Authorizing;
583     if (!m_widget->CheckBeforeLaunch()) {
584         LogError("CheckBeforeLaunch failed, stop launchStep");
585         DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
586             NextStepEvent());
587         return;
588     }
589     LogInfo("Widget launch accepted. Entering running state");
590     m_widgetState = WidgetState_Running;
591
592     cbs->loadFinish = DPL::MakeDelegate(this, &WrtClient::loadFinishCallback);
593     cbs->bufferSet = DPL::MakeDelegate(this, &WrtClient::setLayout);
594     cbs->bufferUnset = DPL::MakeDelegate(this, &WrtClient::unsetLayout);
595     cbs->webkitExit = DPL::MakeDelegate(this, &WrtClient::webkitExitCallback);
596     cbs->webCrash = DPL::MakeDelegate(this, &WrtClient::webCrashCallback);
597     cbs->toggleFullscreen = DPL::MakeDelegate(
598             m_windowData.get(), &WindowData::toggleFullscreen);
599
600     m_widget->SetUserDelegates(cbs);
601     m_widget->Show();
602
603     m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
604
605     ADD_PROFILING_POINT("launchStep", "stop");
606 }
607
608 void WrtClient::initializeWindowModes()
609 {
610     Assert(m_windowData);
611     Assert(m_dao);
612     auto windowModes = m_dao->getWindowModes();
613     bool fullscreen = false;
614     bool backbutton = false;
615     if (m_dao->getWidgetType().appType == WrtDB::APP_TYPE_TIZENWEBAPP) {
616         WidgetSettings widgetSettings;
617         m_dao->getWidgetSettings(widgetSettings);
618         WidgetSettingList settings(widgetSettings);
619         backbutton =
620             (settings.getBackButtonPresence() == BackButton_Enable);
621     }
622
623     FOREACH(it, windowModes)
624     {
625         std::string viewMode = DPL::ToUTF8String(*it);
626         if (viewMode == VIEWMODE_TYPE_FULLSCREEN) {
627             fullscreen = true;
628             break;
629         } else if (viewMode == VIEWMODE_TYPE_MAXIMIZED) {
630             break;
631         }
632     }
633
634     m_windowData->setViewMode(fullscreen,
635                               backbutton);
636 }
637
638 void WrtClient::backButtonCallback(void* data,
639                                    Evas_Object * /*obj*/,
640                                    void * /*event_info*/)
641 {
642     LogInfo("BackButtonCallback");
643     Assert(data);
644
645     WrtClient* This = static_cast<WrtClient*>(data);
646
647     This->m_widget->Backward();
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::setOrientationWindow(void)
662 {
663     Assert(m_windowData);
664     Assert(m_dao);
665
666     WidgetSettings widgetSettings;
667     m_dao->getWidgetSettings(widgetSettings);
668     WidgetSettingList settings(widgetSettings);
669     WidgetSettingScreenLock rotationValue = settings.getRotationValue();
670     if (rotationValue == Screen_Portrait) {
671         elm_win_wm_rotation_preferred_rotation_set(
672             m_windowData->m_win,
673             WIN_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
674     } else if (rotationValue == Screen_Landscape) {
675         elm_win_wm_rotation_preferred_rotation_set(
676             m_windowData->m_win,
677             WIN_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE);
678     } else {
679         elm_win_wm_rotation_preferred_rotation_set(
680             m_windowData->m_win,
681             WIN_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
682     }
683 }
684
685 void WrtClient::setOrientationEwk(void)
686 {
687     Assert(m_widget);
688     Assert(m_dao);
689
690     WidgetSettings widgetSettings;
691     m_dao->getWidgetSettings(widgetSettings);
692     WidgetSettingList settings(widgetSettings);
693     WidgetSettingScreenLock rotationValue = settings.getRotationValue();
694     if (rotationValue == Screen_Portrait) {
695         ewk_view_orientation_send(
696             m_widget->GetCurrentWebview(),
697              W3C_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
698     } else if (rotationValue == Screen_Landscape) {
699         ewk_view_orientation_send(
700             m_widget->GetCurrentWebview(),
701             W3C_ORIENTATION_LANDSCAPE_PRIMARY_ANGLE);
702     } else {
703         ewk_view_orientation_send(
704             m_widget->GetCurrentWebview(),
705             W3C_ORIENTATION_PORTRAIT_PRIMARY_ANGLE);
706     }
707 }
708
709 void WrtClient::connectElmCallback()
710 {
711     Assert(m_windowData);
712     Assert(m_dao);
713     WidgetSettings widgetSettings;
714     m_dao->getWidgetSettings(widgetSettings);
715     WidgetSettingList settings(widgetSettings);
716     if (settings.getBackButtonPresence() == BackButton_Enable) {
717         m_windowData->addFloatBackButtonCallback(
718             "clicked",
719             &WrtClient::backButtonCallback,
720             this);
721     }
722 }
723
724 void WrtClient::setLayout(Evas_Object* newBuffer)
725 {
726     LogDebug("add new webkit buffer to window");
727     Assert(newBuffer);
728
729     elm_object_part_content_set(m_windowData->m_user_layout,
730                                 ELM_SWALLOW_CONTENT,
731                                 newBuffer);
732
733     evas_object_show(newBuffer);
734 }
735
736 void WrtClient::unsetLayout(Evas_Object* currentBuffer)
737 {
738     LogDebug("remove current webkit buffer from window");
739     Assert(currentBuffer);
740     evas_object_hide(currentBuffer);
741
742     elm_object_part_content_unset(m_windowData->m_user_layout,
743                                   ELM_SWALLOW_CONTENT);
744 }
745
746 void WrtClient::shutdownStep()
747 {
748     LogDebug("Closing Wrt connection ...");
749
750     if (m_widget && m_widgetState) {
751         m_widgetState = WidgetState_Stopped;
752         m_widget->Hide();
753         m_widget.reset();
754         ewk_context_delete(s_preparedEwkContext);
755         PrepareExternalStorageSingleton::Instance().Deinitialize();
756         WRT::CoreModuleSingleton::Instance().Terminate();
757     }
758     if (m_initialized) {
759         m_initialized = false;
760     }
761     m_windowData.reset();
762     Quit();
763 }
764
765 int WrtClient::languageChangedCallback(void *data)
766 {
767     LogDebug("Language Changed");
768     if (!data) {
769         return 0;
770     }
771     WrtClient* wrtClient = static_cast<WrtClient*>(data);
772     if (!(wrtClient->m_dao)) {
773         return 0;
774     }
775
776     // reset function fetches system locales and recreates language tags
777     LanguageTagsProviderSingleton::Instance().resetLanguageTags();
778     // widget default locales are added to language tags below
779     DPL::OptionalString defloc = wrtClient->m_dao->getDefaultlocale();
780     if (!defloc.IsNull()) {
781         LanguageTagsProviderSingleton::Instance().addWidgetDefaultLocales(
782             *defloc);
783     }
784
785     if (wrtClient->m_launched &&
786         wrtClient->m_widgetState != WidgetState_Stopped)
787     {
788         wrtClient->m_widget->ReloadStartPage();
789     }
790     return 0;
791 }
792
793 void WrtClient::Quit()
794 {
795     ewk_shutdown();
796     DPL::Application::Quit();
797 }
798
799 static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler)
800 {
801     int fd = ecore_main_fd_handler_fd_get(handler);
802
803     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
804     {
805         LogDebug("ECORE_FD_ERROR");
806
807         if (fd != -1)
808         {
809             close(fd);
810         }
811
812         exit(-1);
813         return ECORE_CALLBACK_CANCEL;
814     }
815
816     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
817     {
818         LogDebug("ECORE_FD_READ");
819         {
820             app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
821             memset(pkt, 0, AUL_SOCK_MAXBUFF);
822
823             int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
824
825             if (fd != -1)
826             {
827                 close(fd);
828             }
829
830             if (recv_ret == -1)
831             {
832                 LogDebug("recv error!");
833                 exit(-1);
834             }
835             LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len);
836
837             ecore_main_fd_handler_del(handler);
838
839             __wrt_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv);
840
841             free(pkt);
842         }
843
844         ecore_main_loop_quit();
845         return ECORE_CALLBACK_CANCEL;
846     }
847
848     return ECORE_CALLBACK_CANCEL;
849 }
850
851
852 static void vconf_changed_handler(keynode_t *key, void *data)
853 {
854     LogInfo("VCONFKEY_LANGSET vconf-key was changed!");
855
856     exit(-1);
857 }
858
859 void set_env()
860 {
861     // set evas backend type
862     if (!getenv("ELM_ENGINE"))
863     {
864         if (!setenv("ELM_ENGINE", "gl", 1))
865         {
866             LogDebug("Enable backend");
867         }
868     }
869     else
870     {
871         LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
872     }
873
874 #ifndef TIZEN_PUBLIC
875     setenv("COREGL_FASTPATH", "1", 1);
876 #endif
877     setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
878     setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
879     setenv("ELM_IMAGE_CACHE", "0", 1);
880 }
881
882 int main(int argc,
883          char *argv[])
884 {
885     // process pool - store arg's value
886     app_argc = argc;
887     app_argv = argv;
888
889     UNHANDLED_EXCEPTION_HANDLER_BEGIN
890     {
891         ADD_PROFILING_POINT("main-entered", "point");
892
893         // Set log tagging
894         DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
895
896         // Set environment variables
897         set_env();
898
899         if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d"))
900         {
901             LogInfo("Entered dummy process mode");
902             sprintf(argv[0], "%s                                              ",
903                     DUMMY_PROCESS_PATH);
904
905             LogInfo("Prepare ewk_context");
906             appcore_set_i18n("wrt-client", NULL);
907             ewk_set_arguments(argc, argv);
908             setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
909             s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
910
911             if (s_preparedEwkContext == NULL)
912             {
913                 LogInfo("Creating webkit context was failed!");
914                 exit(-1);
915             }
916
917             LogInfo("ewk_context_certificate_file_set()");
918             ewk_context_certificate_file_set(s_preparedEwkContext, caCertPath);
919
920             int client_fd = __connect_process_pool_server();
921
922             if (client_fd == -1)
923             {
924                 LogInfo("Connecting process_pool_server was failed!");
925                 exit(-1);
926             }
927
928             // register language change callback
929             vconf_notify_key_changed(VCONFKEY_LANGSET, vconf_changed_handler, NULL);
930
931             LogInfo("Prepare window_data");
932             // Temporarily change HOME path to app
933             // This change is needed for getting elementary profile
934             // /opt/home/app/.elementary/config/mobile/base.cfg
935             const char* backupEnv = getenv(HOME);
936             setenv(HOME, APP_HOME_PATH, 1);
937             LogInfo("elm_init()");
938             elm_init(argc, argv);
939             setenv(HOME, backupEnv, 1);
940
941             LogInfo("WindowData()");
942             s_preparedWindowData = new WindowData(static_cast<unsigned long>(getpid()));
943
944             Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd,
945                                            (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR),
946                                            proces_pool_fd_handler, NULL, NULL, NULL);
947
948             if (fd_handler == NULL)
949             {
950                 LogInfo("fd_handler is NULL");
951                 exit(-1);
952             }
953
954             setpriority(PRIO_PROCESS, 0, 0);
955
956             LogDebug("ecore_main_loop_begin()");
957             ecore_main_loop_begin();
958             LogDebug("ecore_main_loop_begin()_end");
959
960             // deregister language change callback
961             vconf_ignore_key_changed(VCONFKEY_LANGSET, vconf_changed_handler);
962
963             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
964             PluginModuleSupport::init(s_preparedEwkContext, tizenId);
965
966         }
967         else
968         {
969             // This code is to fork a web process without exec.
970             std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
971
972             if (!tizenId.empty())
973             {
974 #ifdef MULTIPROCESS_SERVICE_SUPPORT
975                 std::size_t pos = tizenId.find("-__SERVICE_PROCESS__");
976                 if (pos != std::string::npos) {
977                     tizenId.erase(pos);
978                 }
979 #endif
980                 LogDebug("Launching by fork mode");
981                 // Language env setup
982                 appcore_set_i18n("wrt-client", NULL);
983                 ewk_set_arguments(argc, argv);
984                 setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
985                 s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
986                         BUNDLE_PATH);
987
988                 if (s_preparedEwkContext == NULL)
989                 {
990                     LogInfo("Creating webkit context was failed!");
991                     Wrt::Popup::PopupInvoker().showInfo("Error", "Creating webkit context was failed.", "OK");
992                     exit(-1);
993                 }
994
995                 // plugin init
996                 PluginModuleSupport::init(s_preparedEwkContext, tizenId);
997
998                 LogInfo("ewk_context_certificate_file_set()");
999                 ewk_context_certificate_file_set(s_preparedEwkContext, caCertPath);
1000             }
1001         }
1002
1003         // Output on stdout will be flushed after every newline character,
1004         // even if it is redirected to a pipe. This is useful for running
1005         // from a script and parsing output.
1006         // (Standard behavior of stdlib is to use full buffering when
1007         // redirected to a pipe, which means even after an end of line
1008         // the output may not be flushed).
1009         setlinebuf(stdout);
1010
1011         WrtClient app(app_argc, app_argv);
1012
1013         ADD_PROFILING_POINT("Before appExec", "point");
1014         int ret = app.Exec();
1015         LogDebug("App returned: " << ret);
1016         ret = app.getReturnStatus();
1017         LogDebug("WrtClient returned: " << ret);
1018         return ret;
1019     }
1020     UNHANDLED_EXCEPTION_HANDLER_END
1021 }