Fixed recovery widget during preinstallation
[platform/framework/web/wrt-installer.git] / src / wrt-installer / wrt_installer.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 /* @file    wrt_installer.cpp
17  * @version 1.0
18  * @brief   Implementation file for installer
19  */
20
21 #include "wrt_installer.h"
22 #include "plugin_utils.h"
23
24 #include <cstdlib>
25 #include <string>
26 #include <fstream>
27 #include <unistd.h>
28 #include <memory>
29 #include <sys/resource.h>
30 #include <dpl/optional.h>
31 #include <dpl/scoped_free.h>
32 #include <dpl/optional_typedefs.h>
33 #include <dpl/exception.h>
34 #include <dpl/sstream.h>
35 #include <vconf.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37 #include <dpl/wrt-dao-ro/config_parser_data.h>
38 #include <dpl/localization/localization_utils.h>
39 #include <dpl/optional_typedefs.h>
40 #include <dpl/string.h>
41 #include <dpl/abstract_waitable_input_adapter.h>
42 #include <dpl/abstract_waitable_output_adapter.h>
43 #include <dpl/zip_input.h>
44 #include <dpl/binary_queue.h>
45 #include <dpl/copy.h>
46 #include <dpl/errno_string.h>
47 #include <dpl/utils/wrt_global_settings.h>
48 #include "option_parser.h"
49 #include <parser_runner.h>
50 #include <widget_parser.h>
51 #include <root_parser.h>
52
53 #define NOFILE_CNT_FOR_INSTALLER 9999
54
55 using namespace WrtDB;
56
57 namespace { // anonymous
58 const char AUL_ARG_KEY[] = "widget_arg";
59 const char * const PKGMGR_INSTALL_MSG = "Install widget";
60 const char * const PKGMGR_UNINSTALL_MSG = "Uninstall widget";
61
62 const double BASE_LAYOUT_W = 720.0f;
63 const double BASE_LAYOUT_H = 1280.0f;
64
65 const char * const CONFIG_XML = "config.xml";
66 const char * const HYBRID_CONFIG_XML = "res/wgt/config.xml";
67
68 struct free_deleter
69 {
70     void operator()(void* x)
71     {
72         free(x);
73     }
74 };
75
76 struct PluginInstallerData
77 {
78     void* wrtInstaller;
79     std::string pluginPath;
80 };
81 } // namespace anonymous
82
83 WrtInstaller::WrtInstaller(int argc, char **argv) :
84     Application(argc, argv, "backend", false),
85     DPL::TaskDecl<WrtInstaller>(this),
86     m_installPolicy(WRT_WIM_NOT_INSTALLED),
87     m_packagePath(),
88     m_handle(-1),
89     m_initialized(false),
90     m_numPluginsToInstall(0),
91     m_totalPlugins(0),
92     m_returnStatus(-1),
93     m_installByPkgmgr(false),
94     m_quiet(true),
95     m_popup(NULL),
96     m_startupPluginInstallation(false),
97     m_preloadWidget(false)
98 {
99     Touch();
100     LogDebug("App Created");
101 }
102
103 WrtInstaller::~WrtInstaller()
104 {
105     LogDebug("App Finished");
106 }
107
108 void WrtInstaller::OnStop()
109 {
110     LogInfo("Stopping Dummy Client");
111 }
112
113 void WrtInstaller::OnCreate()
114 {
115     LogInfo("Creating DummyClient");
116     fprintf(stderr,
117             "===========================================================\n");
118     fprintf(stderr, "# wrt-installer #\n");
119     fprintf(stderr, "# argc [%d]\n", m_argc);
120     fprintf(stderr, "# argv[0] = [%s]\n", m_argv[0]);
121     fprintf(stderr, "# argv[1] = [%s]\n", m_argv[1]);
122     fprintf(stderr, "# argv[2] = [%s]\n", m_argv[2]);
123     fprintf(stderr,
124             "===========================================================\n");
125
126     AddStep(&WrtInstaller::initStep);
127
128     std::string arg = m_argv[0];
129
130     pkgmgrSignalInterface =
131         std::static_pointer_cast<PackageManager::IPkgmgrSignal>(
132             std::shared_ptr<PackageManager::PkgmgrSignalDummy>(
133                 new PackageManager::PkgmgrSignalDummy()
134                 )
135             );
136
137     if (arg.empty()) {
138         return showHelpAndQuit();
139     }
140
141     installNewPlugins();
142
143     if (arg.find("wrt-installer") != std::string::npos) {
144         if (m_argc <= 1) {
145             return showHelpAndQuit();
146         }
147
148         arg = m_argv[1];
149         if (arg == "-h" || arg == "--help") {
150             if (m_argc != 2) {
151                 return showHelpAndQuit();
152             }
153
154             // Just show help
155             return showHelpAndQuit();
156         } else if (arg == "-p" || arg == "--install-plugins") {
157             if (m_argc != 2) {
158                 return showHelpAndQuit();
159             }
160             if (!m_startupPluginInstallation) {
161                 AddStep(&WrtInstaller::installPluginsStep);
162             } else {
163                 LogInfo("Plugin installation alredy started");
164             }
165         } else if (arg == "-i" || arg == "--install") {
166             if (m_argc != 3) {
167                 return showHelpAndQuit();
168             }
169
170             struct stat info;
171             if (-1 != stat(m_argv[2], &info) && S_ISDIR(info.st_mode)) {
172                 LogInfo("Installing package directly from directory");
173                 m_installPolicy = WRT_WIM_POLICY_DIRECTORY_FORCE_INSTALL;
174             } else {
175                 LogInfo("Installing from regular location");
176                 m_installPolicy = WRT_WIM_POLICY_WAC;
177             }
178             m_packagePath = m_argv[2];
179             AddStep(&WrtInstaller::installStep);
180         } else if (arg == "-if" || arg == "--install-force") {
181             if (m_argc != 3) {
182                 return showHelpAndQuit();
183             }
184
185             m_packagePath = m_argv[2];
186             m_installPolicy = WRT_WIM_POLICY_FORCE_INSTALL;
187             AddStep(&WrtInstaller::installStep);
188         } else if (arg == "-il" || arg == "--install-preload") {
189             if (m_argc != 3) {
190                 return showHelpAndQuit();
191             }
192
193             m_packagePath = m_argv[2];
194             m_preloadWidget = true;
195             m_installPolicy = WRT_WIM_POLICY_WAC;
196             AddStep(&WrtInstaller::installStep);
197         } else if (arg == "-un" || arg == "--uninstall-name") {
198             if (m_argc != 3) {
199                 return showHelpAndQuit();
200             }
201             m_name = m_argv[2];
202             AddStep(&WrtInstaller::uninstallPkgNameStep);
203         } else if (arg == "-ug" || arg == "--uninstall-guid") {
204             if (m_argc != 3) {
205                 return showHelpAndQuit();
206             }
207             m_name = m_argv[2];
208             AddStep(&WrtInstaller::uninstallGuidStep);
209         } else if (arg == "-up" || arg == "--uninstall-packagepath") {
210             if (m_argc != 3) {
211                 return showHelpAndQuit();
212             }
213             m_packagePath = m_argv[2];
214             AddStep(&WrtInstaller::unistallWgtFileStep);
215         } else {
216             return showHelpAndQuit();
217         }
218     } else if (arg.find("backend") != std::string::npos) {
219         using namespace PackageManager;
220         m_installByPkgmgr = true;
221
222         auto pkgmgrSignal = std::shared_ptr<PackageManager::PkgmgrSignal>(
223                 new PackageManager::PkgmgrSignal()
224                 );
225
226         pkgmgrSignal->initialize(m_argc, m_argv);
227         m_quiet = pkgmgrSignal->isNoPopupRequired();
228         LogDebug("backend m_quiet" << m_quiet);
229
230         int reqType = pkgmgrSignal->getRequestedType();
231
232         pkgmgrSignalInterface =
233             std::static_pointer_cast<PackageManager::IPkgmgrSignal>(
234                 pkgmgrSignal);
235         switch (reqType) {
236         case PKGMGR_REQ_INSTALL:
237             m_packagePath = m_argv[4];
238             struct stat info;
239             if (-1 != stat(m_argv[4], &info) && S_ISDIR(info.st_mode)) {
240                 LogInfo("Installing package directly from directory");
241                 m_installPolicy = WRT_WIM_POLICY_DIRECTORY_FORCE_INSTALL;
242             } else {
243                 LogInfo("Installing from regular location");
244                 m_installPolicy = WRT_WIM_POLICY_WAC;
245             }
246             AddStep(&WrtInstaller::installStep);
247             break;
248         case PKGMGR_REQ_UNINSTALL:
249             m_name = m_argv[4];
250             AddStep(&WrtInstaller::uninstallPkgNameStep);
251             break;
252         default:
253             LogDebug("Not available type");
254             break;
255         }
256     }
257
258     AddStep(&WrtInstaller::shutdownStep);
259     DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>::
260         PostEvent(
261         WRTInstallerNS::NextStepEvent());
262 }
263
264 void WrtInstaller::OnReset(bundle *b)
265 {
266     const char * bundledVal = bundle_get_val(b, AUL_ARG_KEY);
267     if (bundledVal != NULL) {
268         m_bundleValue = bundledVal;
269         LogInfo("Bundled value for (" << AUL_ARG_KEY << ") key received: " <<
270                 m_bundleValue);
271     }
272 }
273
274 int WrtInstaller::getReturnStatus() const
275 {
276     if (!m_returnStatus) {
277         return RE_SUCCESS;
278     } else {
279         return RE_FAIL;
280     }
281 }
282
283 void WrtInstaller::OnTerminate()
284 {
285     LogDebug("Wrt Shutdown now");
286     PluginUtils::unlockPluginInstallation();
287     if (m_initialized) {
288         wrt_installer_shutdown();
289     }
290     delete m_popup;
291 }
292
293 void WrtInstaller::showHelpAndQuit()
294 {
295     printf("Usage: wrt-installer [OPTION]... [WIDGET: ID/NAME/GUID/PATH]...\n"
296            "Operate with WebRuntime daemon: install, uninstall"
297            " and launch widgets.\n"
298            "Query list of installed widgets and setup up debugging support.\n"
299            "\n"
300            "Exactly one option must be selected.\n"
301            "Mandatory arguments to long options are mandatory for short "
302            "options too.\n"
303            "  -h,    --help                                 show this help\n"
304            "  -p,    --install-plugins                      install plugins\n"
305            "  -i,    --install                              "
306            "install or update widget package for given path\n"
307            "  -if,   --install-force                        "
308            "install forcibly widget package for given path\n"
309            "  -un,   --uninstall-name                       "
310            "uninstall widget for given package name\n"
311            "  -ug,   --uninstall-guid                       "
312            "uninstall widget for given Global Unique IDentifier\n"
313            "  -up,   --uninstall-packagepath                "
314            "uninstall widget for given package file path\n"
315            "\n");
316
317     Quit();
318 }
319
320 void WrtInstaller::OnEventReceived(const WRTInstallerNS::QuitEvent& /*event*/)
321 {
322     LogDebug("Quiting");
323
324     if (m_initialized) {
325         LogDebug("Wrt Shutdown now");
326         SwitchToStep(&WrtInstaller::shutdownStep);
327         DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>::
328             PostEvent(
329             WRTInstallerNS::NextStepEvent());
330     } else {
331         LogDebug("Quiting application");
332         return Quit();
333     }
334 }
335
336 void WrtInstaller::OnEventReceived(
337     const WRTInstallerNS::NextStepEvent& /*event*/)
338 {
339     LogDebug("Executing next step");
340     NextStep();
341 }
342
343 void WrtInstaller::OnEventReceived(
344     const WRTInstallerNS::InstallPluginEvent& /*event*/)
345 {
346     PluginInstallerData* privateData = new PluginInstallerData;
347     privateData->wrtInstaller = this;
348
349     if (!(*m_pluginsPaths).empty()) {
350         privateData->pluginPath = (*m_pluginsPaths).front();
351         (*m_pluginsPaths).pop_front();
352
353         wrt_install_plugin(privateData->pluginPath.c_str(),
354                            static_cast<void*>(privateData),
355                            &staticWrtPluginInstallationCallback,
356                            &staticWrtPluginInstallProgressCb);
357     } else {
358         delete privateData;
359     }
360 }
361
362 void WrtInstaller::initStep()
363 {
364     wrt_installer_init(this, staticWrtInitCallback);
365 }
366
367 void WrtInstaller::installStep()
368 {
369     LogDebug("Installing widget ...");
370     std::unique_ptr<char, free_deleter> packagePath(canonicalize_file_name(
371                                                         m_packagePath.c_str()));
372
373     wrt_install_widget(packagePath ? packagePath.get() : m_packagePath.c_str(),
374                        this, &staticWrtStatusCallback,
375                        (!m_quiet || m_installByPkgmgr)
376                        ? &staticWrtInstallProgressCallback : NULL,
377                        m_installPolicy,
378                        m_quiet,
379                        m_preloadWidget,
380                        pkgmgrSignalInterface);
381 }
382
383 void WrtInstaller::installPluginsStep()
384 {
385     LogDebug("Installing plugins ...");
386     fprintf(stderr, "Installing plugins ...\n");
387
388     if (m_startupPluginInstallation) {
389         LogInfo("Plugin installation started because new plugin package found");
390     } else if (!PluginUtils::lockPluginInstallation()) {
391         LogError("Failed to open plugin installation lock file"
392                  " Plugins are currently installed by other process");
393         staticWrtPluginInstallationCallback(WRT_PLUGIN_INSTALLER_ERROR_LOCK,
394                                             this);
395         return;
396     }
397
398     std::string PLUGIN_PATH = std::string(GlobalConfig::GetDevicePluginPath());
399
400     DIR *dir;
401     dir = opendir(PLUGIN_PATH.c_str());
402
403     if (!dir) {
404         return;
405     }
406
407     LogInfo("Plugin DIRECTORY IS" << PLUGIN_PATH);
408
409     std::list<std::string> pluginsPaths;
410     struct dirent libdir;
411     struct dirent *result;
412     int return_code;
413     errno = 0;
414     for (return_code = readdir_r(dir, &libdir, &result);
415             result != NULL && return_code == 0;
416             return_code = readdir_r(dir, &libdir, &result))
417     {
418         if (strcmp(libdir.d_name, ".") == 0 ||
419             strcmp(libdir.d_name, "..") == 0)
420         {
421             continue;
422         }
423
424         std::string path = PLUGIN_PATH;
425         path += "/";
426         path += libdir.d_name;
427
428         struct stat tmp;
429
430         if (stat(path.c_str(), &tmp) == -1) {
431             LogError("Failed to open file" << path);
432             continue;
433         }
434
435         if (!S_ISDIR(tmp.st_mode)) {
436             LogError("Not a directory" << path);
437             continue;
438         }
439
440         pluginsPaths.push_back(path);
441     }
442
443     if (return_code != 0 || errno != 0) {
444         LogError("readdir_r() failed with " << DPL::GetErrnoString());
445     }
446
447     //set nb of plugins to install
448     //this value indicate how many callbacks are expected
449     m_numPluginsToInstall = pluginsPaths.size();
450     LogInfo("Plugins to install: " << m_numPluginsToInstall);
451     m_pluginsPaths = pluginsPaths;
452
453     m_totalPlugins = m_numPluginsToInstall;
454     DPL::Event::ControllerEventHandler<WRTInstallerNS::InstallPluginEvent>
455         ::PostEvent(WRTInstallerNS::InstallPluginEvent());
456
457     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
458         LogError("Failed to close dir: " << PLUGIN_PATH << " with error: "
459                                          << DPL::GetErrnoString());
460     }
461 }
462
463 void WrtInstaller::uninstallPkgNameStep()
464 {
465     LogDebug("Uninstalling widget ...");
466     LogDebug("Package name : " << m_name);
467     wrt_uninstall_widget(m_name.c_str(), this, &staticWrtStatusCallback,
468                          (!m_quiet || m_installByPkgmgr)
469                          ? &staticWrtUninstallProgressCallback : NULL,
470                          pkgmgrSignalInterface);
471 }
472
473 void WrtInstaller::uninstallGuidStep()
474 {
475     LogDebug("Uninstalling widget ...");
476     std::string appid;
477     WrtErrStatus status = wrt_get_widget_by_guid(appid, m_name);
478     if (status == WRT_SUCCESS) {
479         LogDebug("Guid : " << m_name);
480         wrt_uninstall_widget(
481             appid.c_str(), this, &staticWrtStatusCallback,
482             !m_quiet ? &staticWrtUninstallProgressCallback :
483             NULL,
484             pkgmgrSignalInterface);
485     } else {
486         printf("failed: can not uninstall widget\n");
487         LogError("Fail to uninstalling widget... ");
488         m_returnStatus = -1;
489         DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
490             PostEvent(
491             WRTInstallerNS::QuitEvent());
492     }
493 }
494
495 void WrtInstaller::unistallWgtFileStep()
496 {
497     LogDebug("Uninstalling widget ...");
498
499     Try {
500         // Parse config
501         ParserRunner parser;
502         ConfigParserData configInfo;
503
504         // Open zip file
505         std::unique_ptr<DPL::ZipInput> zipFile(
506             new DPL::ZipInput(m_packagePath));
507         std::unique_ptr<DPL::ZipInput::File> configFile;
508
509         Try {
510             // Open config.xml file
511             configFile.reset(zipFile->OpenFile(CONFIG_XML));
512         }
513         Catch(DPL::ZipInput::Exception::OpenFileFailed)
514         {
515             // Open config.xml file for hybrid
516             configFile.reset(zipFile->OpenFile(HYBRID_CONFIG_XML));
517         }
518
519         // Extract config
520         DPL::BinaryQueue buffer;
521         DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
522         DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
523         DPL::Copy(&inputAdapter, &outputAdapter);
524         parser.Parse(&buffer,
525                      ElementParserPtr(
526                          new RootParser<WidgetParser>(configInfo,
527                                                       DPL::FromUTF32String(
528                                                           L"widget"))));
529
530         DPL::OptionalString pkgId = configInfo.tizenPkgId;
531         if (!pkgId.IsNull()) {
532             LogDebug("Pkgid from packagePath : " << pkgId);
533             wrt_uninstall_widget(
534                 DPL::ToUTF8String(*pkgId).c_str(), this, &staticWrtStatusCallback,
535                 !m_quiet ? &staticWrtUninstallProgressCallback
536                 : NULL,
537                 pkgmgrSignalInterface);
538         } else {
539             LogError("Fail to uninstalling widget... ");
540             m_returnStatus = -1;
541             DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
542                 PostEvent(
543                 WRTInstallerNS::QuitEvent());
544         }
545     }
546     Catch(DPL::ZipInput::Exception::OpenFailed)
547     {
548         LogError("Failed to open widget package");
549         printf("failed: widget package does not exist\n");
550         m_returnStatus = -1;
551         DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
552             PostEvent(
553             WRTInstallerNS::QuitEvent());
554     }
555     Catch(DPL::ZipInput::Exception::OpenFileFailed)
556     {
557         printf("failed: widget config file does not exist\n");
558         LogError("Failed to open config.xml file");
559         m_returnStatus = -1;
560         DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
561             PostEvent(
562             WRTInstallerNS::QuitEvent());
563     }
564     Catch(ElementParser::Exception::ParseError)
565     {
566         printf("failed: can not parse config file\n");
567         LogError("Failed to parse config.xml file");
568         m_returnStatus = -1;
569         DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
570             PostEvent(
571             WRTInstallerNS::QuitEvent());
572     }
573 }
574
575 void WrtInstaller::shutdownStep()
576 {
577     LogDebug("Closing Wrt connection ...");
578     if (m_initialized) {
579         wrt_installer_shutdown();
580         m_initialized = false;
581         DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
582             PostEvent(
583             WRTInstallerNS::QuitEvent());
584     }
585 }
586
587 void WrtInstaller::staticWrtInitCallback(WrtErrStatus status,
588                                          void* userdata)
589 {
590     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
591     Assert(This);
592
593     if (status == WRT_SUCCESS) {
594         LogDebug("Init succesfull");
595         This->m_initialized = true;
596         This->m_returnStatus = 0;
597
598         if (This->popupsEnabled()) {
599             This->m_popup = new InstallerPopup;
600             This->m_popup->init();
601         }
602
603         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
604             ::PostEvent(WRTInstallerNS::NextStepEvent());
605     } else {
606         LogError("Init unsuccesfull");
607         This->m_returnStatus = -1;
608         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>::
609             PostEvent(
610             WRTInstallerNS::QuitEvent());
611     }
612 }
613
614 void WrtInstaller::staticWrtStatusCallback(std::string tizenId,
615                                            WrtErrStatus status,
616                                            void* userdata)
617 {
618     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
619     Assert(This);
620
621     Step current = This->GetCurrentStep();
622     DPL::String resultMsg;
623     std::string printMsg;
624
625     if (current == &WrtInstaller::installStep) {
626         resultMsg = DPL::FromUTF8String(PKGMGR_INSTALL_MSG);
627         printMsg = "installation";
628     } else if (current == &WrtInstaller::uninstallPkgNameStep ||
629                current == &WrtInstaller::uninstallGuidStep ||
630                current == &WrtInstaller::unistallWgtFileStep)
631     {
632         resultMsg = DPL::FromUTF8String(PKGMGR_UNINSTALL_MSG);
633         printMsg = "uninstallation";
634     }
635
636     if (WRT_SUCCESS != status) {
637         // Failure
638         LogError("Step failed");
639         This->m_returnStatus = -1;
640
641         if (This->popupsEnabled()) {
642             resultMsg += L" : " + DPL::FromUTF8String(PKGMGR_END_FAILURE);
643             This->m_popup->showPopup(This, resultMsg, failResultCallback);
644         } else {
645             This->DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>
646                 ::PostEvent(WRTInstallerNS::QuitEvent());
647         }
648
649         switch (status) {
650             case WRT_INSTALLER_ERROR_INVALID_WIDGET_PACKAGE:
651                 This->m_returnStatus = 1; //this status is specific
652                 fprintf(stderr, "## wrt-installer : %s %s has failed - invalid widget package\n",
653                         tizenId.c_str(), printMsg.c_str());
654                 break;
655
656             case WRT_INSTALLER_ERROR_WIDGET_DOES_NOT_EXIST:
657                 fprintf(stderr, "## wrt-installer : %s %s has failed - widget package does not exist\n",
658                         tizenId.c_str(), printMsg.c_str());
659                 break;
660
661             case WRT_INSTALLER_ERROR_ALREADY_UNINSTALLING:
662                 fprintf(stderr, "## wrt-installer : %s %s has failed - already uninstalling\n",
663                         tizenId.c_str(), printMsg.c_str());
664                 break;
665
666             case WRT_INSTALLER_ERROR_INVALID_CERTIFICATE:
667                 fprintf(stderr,"## wrt-installer : %s %s has failed - invalid certificate - invalid signature\n",
668                         tizenId.c_str(), printMsg.c_str());
669                 break;
670
671             case WRT_INSTALLER_ERROR_ALREADY_INSTALLED:
672                 fprintf(stderr,"## wrt-installer : %s %s has failed - already installed\n",
673                         tizenId.c_str(), printMsg.c_str());
674                 break;
675
676             case WRT_INSTALLER_ERROR_INTERNAL:
677                 fprintf(stderr,"## wrt-installer : %s %s has failed - internal error\n",
678                         tizenId.c_str(), printMsg.c_str());
679                 break;
680
681             case WRT_INSTALLER_ERROR_NOT_ALLOWED:
682                 fprintf(stderr,"## wrt-installer : %s %s has failed - installation or update not allowed; invalid"
683                        " mode\n", tizenId.c_str(), printMsg.c_str());
684                 break;
685
686             case WRT_INSTALLER_ERROR_DEFERRED:
687                 fprintf(stderr,"## wrt-installer : deferred: widget update will continue after the widget"
688                        " has been stopped\n");
689                 break;
690
691             case WRT_INSTALLER_ERROR_DATABASE_FAILURE:
692                 fprintf(stderr,"## wrt-installer : %s %s has failed - database failure\n",
693                         tizenId.c_str(), printMsg.c_str());
694                 break;
695
696             case WRT_INSTALLER_ERROR_OSPSVC:
697                 fprintf(stderr,"## wrt-installer : %s %s has failed - during installation or"
698                         " uninstallation osp service\n", tizenId.c_str(),
699                         printMsg.c_str());
700                 break;
701
702             case WRT_INSTALLER_ERROR_UNKNOWN:
703                 fprintf(stderr,"## wrt-installer : %s %s has failed - unknown error\n",
704                         tizenId.c_str(), printMsg.c_str());
705                 break;
706
707             default:
708                 break;
709         }
710     } else {
711         fprintf(stderr,
712                 "## wrt-installer : %s %s was successful.\n",
713                 tizenId.c_str(),
714                 printMsg.c_str());
715         LogDebug("Status succesfull");
716         This->m_returnStatus = 0;
717         resultMsg += L" : " + DPL::FromUTF8String(PKGMGR_END_SUCCESS);
718
719         if (This->popupsEnabled()) {
720             This->m_popup->showPopup(This, resultMsg, showResultCallback);
721         } else {
722             This->DPL::Event::ControllerEventHandler<WRTInstallerNS::
723                                                          NextStepEvent>
724                 ::PostEvent(WRTInstallerNS::NextStepEvent());
725         }
726     }
727 }
728
729 void WrtInstaller::staticWrtPluginInstallationCallback(WrtErrStatus status,
730                                                        void* userdata)
731 {
732     Assert(userdata);
733
734     PluginInstallerData* data = static_cast<PluginInstallerData*>(userdata);
735
736     WrtInstaller *This = static_cast<WrtInstaller*>(data->wrtInstaller);
737
738     std::string path = std::string(data->pluginPath);
739     delete data;
740
741     This->m_numPluginsToInstall--;
742     LogDebug("Plugins to install: " << This->m_numPluginsToInstall);
743
744     if (This->m_numPluginsToInstall < 1) {
745         LogDebug("All plugins installation completed");
746         fprintf(stderr, "All plugins installation completed.\n");
747
748         //remove installation request
749         if (!PluginUtils::removeInstallationRequiredFlag()) {
750             LogInfo("Failed to remove file initializing plugin installation");
751         }
752
753         //remove lock file
754         if (!PluginUtils::unlockPluginInstallation()) {
755             LogInfo("Failed to remove installation lock");
756         }
757
758         if (This->popupsEnabled()) {
759             This->m_popup->init();
760             elm_progressbar_value_set(This->m_popup->m_progressbar, 100.0);
761             evas_object_show(This->m_popup->m_popup);
762         }
763
764         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
765             ::PostEvent(WRTInstallerNS::NextStepEvent());
766     } else {
767         if (This->popupsEnabled()) {
768             This->m_popup->init();
769             float percent =
770                 (This->m_totalPlugins -
771                  This->m_numPluginsToInstall) / (float)This->m_totalPlugins;
772             elm_progressbar_value_set(This->m_popup->m_progressbar, percent);
773             evas_object_show(This->m_popup->m_popup);
774         }
775
776         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::
777                                                      InstallPluginEvent>::
778             PostEvent(
779             WRTInstallerNS::InstallPluginEvent());
780     }
781
782     if (WRT_SUCCESS == status) {
783         This->m_returnStatus = 0;
784         fprintf(stderr,
785                 "## wrt-installer : plugin installation successfull [%s]\n",
786                 path.c_str());
787         LogDebug("One plugin Installation succesfull: " << path);
788         return;
789     }
790
791     // Failure
792     LogWarning("One of the plugins installation failed!: " << path);
793
794     if (WRT_PLUGIN_INSTALLER_ERROR_WAITING == status) {
795         LogInfo("Plugin installation is waiting for dependencies");
796         fprintf(stderr, "## wrt-installer : plugin installation failed [%s]\n",
797                 path.c_str());
798     }
799
800     switch (status) {
801     case WRT_PLUGIN_INSTALLER_ERROR_WRONG_PATH:
802         LogError("failed: wrong path to plugin directory\n");
803         break;
804
805     case WRT_PLUGIN_INSTALLER_ERROR_METAFILE:
806         LogError("failed: plugin metafile error\n");
807         break;
808
809     case WRT_PLUGIN_INSTALLER_ERROR_ALREADY_INSTALLED:
810         LogError("failed: plugin already installed\n");
811         break;
812
813     case WRT_PLUGIN_INSTALLER_ERROR_LIBRARY_ERROR:
814         LogError("failed: plugin library: missing symbols or structures\n");
815         break;
816
817     case WRT_PLUGIN_INSTALLER_ERROR_UNKNOWN:
818         LogError("failed: unknown error\n");
819         break;
820
821     default:
822         break;
823     }
824 }
825
826 void WrtInstaller::staticWrtPluginInstallProgressCb(float percent,
827                                                     const char* description,
828                                                     void* userdata)
829 {
830     PluginInstallerData* data = static_cast<PluginInstallerData*>(userdata);
831
832     std::string path = std::string(data->pluginPath);
833
834     LogInfo("Plugin Installation: " << path <<
835             " progress: " << percent <<
836             "description " << description);
837 }
838
839 void WrtInstaller::staticWrtInstallProgressCallback(float percent,
840                                                     const char* description,
841                                                     void* userdata)
842 {
843     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
844     LogInfo(" progress: " << percent <<
845             " description: " << description);
846
847     if (This->popupsEnabled()) {
848         This->m_popup->init();
849         elm_progressbar_value_set(This->m_popup->m_progressbar, percent / 100.0);
850         evas_object_show(This->m_popup->m_popup);
851     }
852 }
853 void WrtInstaller::staticWrtUninstallProgressCallback(float percent,
854                                                       const char* description,
855                                                       void* userdata)
856 {
857     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
858     LogInfo(" progress: " << percent <<
859             " description: " << description);
860
861     if (This->popupsEnabled()) {
862         This->m_popup->init();
863         elm_progressbar_value_set(This->m_popup->m_progressbar, percent / 100.0);
864         evas_object_show(This->m_popup->m_popup);
865     }
866 }
867
868 WrtInstaller::InstallerPopup::InstallerPopup() :
869     m_win(NULL),
870     m_popup(NULL),
871     m_progressbar(NULL)
872 {}
873
874 WrtInstaller::InstallerPopup::~InstallerPopup()
875 {
876     LogDebug("App Finished");
877 }
878
879 void WrtInstaller::InstallerPopup::init()
880 {
881     LogDebug("Window Init");
882
883     if (m_win == NULL) {
884         // create window
885         m_win = createWin("wrt-installer");
886
887         // create popup
888         m_popup = elm_popup_add(m_win);
889
890         // create progressbar
891         m_progressbar = elm_progressbar_add(m_popup);
892         elm_object_style_set(m_progressbar, "list_progress");
893         elm_progressbar_horizontal_set(m_progressbar, EINA_TRUE);
894         evas_object_size_hint_align_set(m_progressbar, EVAS_HINT_FILL,
895                                         EVAS_HINT_FILL);
896         evas_object_size_hint_weight_set(m_progressbar, EVAS_HINT_EXPAND,
897                                          EVAS_HINT_EXPAND);
898         elm_object_content_set(m_popup, m_progressbar);
899         elm_progressbar_value_set(m_progressbar, 0.0);
900         evas_object_show(m_progressbar);
901
902         evas_object_show(m_popup);
903         evas_object_show(m_win);
904     }
905 }
906
907 Evas_Object* WrtInstaller::InstallerPopup::createWin(const char *name)
908 {
909     Evas_Object *win;
910     win = elm_win_add(NULL, name, ELM_WIN_DIALOG_BASIC);
911
912     int w, h;
913     if (!win) {
914         return NULL;
915     }
916
917     elm_win_alpha_set(win, EINA_TRUE);
918     elm_win_title_set(win, name);
919     elm_win_borderless_set(win, EINA_TRUE);
920     elm_win_raise(win);
921
922     ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
923     evas_object_resize(win, w, h);
924     return win;
925 }
926
927 void WrtInstaller::InstallerPopup::showPopup(void* userdata,
928                                              const DPL::String& pkgMsg,
929                                              ShowResultCallback callback)
930 {
931     Evas_Object *btn;
932
933     LogDebug("Result Popup Created");
934     evas_object_del(m_popup);
935     m_popup = NULL;
936
937     m_popup = elm_popup_add(m_win);
938     if (!m_popup) {
939         return;
940     }
941
942     btn = elm_button_add(m_popup);
943     if (!btn) {
944         evas_object_del(m_popup);
945         return;
946     }
947     elm_object_text_set(btn, "OK");
948     evas_object_smart_callback_add(btn, "clicked", callback, userdata);
949     elm_object_part_content_set(m_popup, "button1", btn);
950     elm_object_part_text_set(m_popup, "title,text", "RESULT");
951     elm_object_text_set(m_popup, DPL::ToUTF8String(pkgMsg).c_str());
952
953     evas_object_show(m_popup);
954     evas_object_show(m_win);
955 }
956
957 void WrtInstaller::showResultCallback(void *data, Evas_Object* /*obj*/,
958                                       void* /*event_info*/)
959 {
960     WrtInstaller *This = static_cast<WrtInstaller*>(data);
961     Assert(This);
962
963     This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
964         ::PostEvent(WRTInstallerNS::NextStepEvent());
965 }
966
967 void WrtInstaller::failResultCallback(void *data, Evas_Object* /*obj*/,
968                                       void* /*event_info*/)
969 {
970     WrtInstaller *This = static_cast<WrtInstaller*>(data);
971     Assert(This);
972
973     This->DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>
974         ::PostEvent(WRTInstallerNS::QuitEvent());
975 }
976
977 void WrtInstaller::installNewPlugins()
978 {
979     LogDebug("Install new plugins");
980
981     if (!PluginUtils::lockPluginInstallation()) {
982         LogInfo("Lock NOT created");
983         return;
984     }
985
986     if (!PluginUtils::checkPluginInstallationRequired()) {
987         LogDebug("Plugin installation not required");
988         PluginUtils::unlockPluginInstallation();
989         return;
990     }
991
992     m_startupPluginInstallation = true;
993     AddStep(&WrtInstaller::installPluginsStep);
994 }
995
996 bool WrtInstaller::popupsEnabled() const
997 {
998     return !m_quiet && !GlobalSettings::PopupsTestModeEnabled();
999 }
1000
1001 int main(int argc, char *argv[])
1002 {
1003     UNHANDLED_EXCEPTION_HANDLER_BEGIN
1004     {
1005         // Output on stdout will be flushed after every newline character,
1006         // even if it is redirected to a pipe. This is useful for running
1007         // from a script and parsing output.
1008         // (Standard behavior of stdlib is to use full buffering when
1009         // redirected to a pipe, which means even after an end of line
1010         // the output may not be flushed).
1011         setlinebuf(stdout);
1012
1013         // Check and re-set the file open limitation
1014         struct rlimit rlim;
1015         if (getrlimit(RLIMIT_NOFILE, &rlim) != -1) {
1016             LogDebug("RLIMIT_NOFILE sft(" << rlim.rlim_cur << ")");
1017             LogDebug("RLIMIT_NOFILE hrd(" << rlim.rlim_max << ")");
1018
1019             if (rlim.rlim_cur < NOFILE_CNT_FOR_INSTALLER) {
1020                 rlim.rlim_cur = NOFILE_CNT_FOR_INSTALLER;
1021                 rlim.rlim_max = NOFILE_CNT_FOR_INSTALLER;
1022                 if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
1023                     LogError("setrlimit is fail!!");
1024                 }
1025             }
1026         } else {
1027             LogError("getrlimit is fail!!");
1028         }
1029
1030         // set evas backend type for emulator
1031         // popup isn't showed in the emulator,
1032         // if backend isn't set to SW backend
1033         if (GlobalSettings::IsEmulator()) {
1034             if (setenv("ELM_ENGINE", "x11", 1)) {
1035                 LogDebug("Enable backend");
1036             }
1037         }
1038
1039         WrtInstaller app(argc, argv);
1040         int ret = app.Exec();
1041         LogDebug("App returned: " << ret);
1042         ret = app.getReturnStatus();
1043         LogDebug("WrtInstaller returned: " << ret);
1044         return ret;
1045     }
1046     UNHANDLED_EXCEPTION_HANDLER_END
1047 }