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