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