98157b9139acb58758442aad6e1c82422b65d95f
[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         LogError("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_ALREADY_UNINSTALLING:
623                 printf("failed: already uninstalling\n");
624                 break;
625
626             case WRT_INSTALLER_ERROR_OUT_OUT_DISK_SPACE:
627                 printf("failed: out of disk space\n");
628                 break;
629
630             case WRT_INSTALLER_ERROR_INVALID_CERTIFICATE:
631                 printf("failed: invalid certificate\n");
632                 break;
633
634             case WRT_INSTALLER_ERROR_ALREADY_INSTALLED:
635                 printf("failed: already installed\n");
636                 break;
637
638             case WRT_INSTALLER_ERROR_INTERNAL:
639                 printf("failed: internal error\n");
640                 break;
641
642             case WRT_INSTALLER_ERROR_NOT_ALLOWED:
643                 printf("failed: installation or update not allowed; invalid"
644                        " mode\n");
645                 break;
646
647             case WRT_INSTALLER_ERROR_DEFERRED:
648                 printf("deferred: widget update will continue after the widget"
649                        " has been stopped\n");
650                 break;
651
652             case WRT_INSTALLER_ERROR_DATABASE_FAILURE:
653                 printf("failed: database failure\n");
654                 break;
655
656             case WRT_INSTALLER_ERROR_OSPSVC:
657                 printf("failed: during installation or uninstallation osp service\n");
658                 break;
659
660             case WRT_INSTALLER_ERROR_UNKNOWN:
661                 printf("failed: unknown error\n");
662                 break;
663
664             default:
665                 break;
666         }
667     } else {
668
669         printf("%s : %s\n", printMsg.c_str(), tizenId.c_str());
670         LogDebug("Status succesfull");
671         This->m_returnStatus = 0;
672         resultMsg +=  L" : " + DPL::FromUTF8String(PKGMGR_END_SUCCESS);
673
674         if (This->popupsEnabled()) {
675             This->m_popup->showPopup(This, resultMsg, showResultCallback);
676         } else {
677             This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
678                 ::PostEvent(WRTInstallerNS::NextStepEvent());
679         }
680     }
681 }
682
683 void WrtInstaller::staticWrtPluginInstallationCallback(WrtErrStatus status,
684                                                     void* userdata)
685 {
686     Assert(userdata);
687
688     PluginInstallerData* data = static_cast<PluginInstallerData*>(userdata);
689
690     WrtInstaller *This = static_cast<WrtInstaller*>(data->wrtInstaller);
691
692     std::string path = std::string(data->pluginPath);
693     delete data;
694
695     This->m_numPluginsToInstall--;
696     LogDebug("Plugins to install: " << This->m_numPluginsToInstall);
697
698     if (This->m_numPluginsToInstall < 1) {
699         LogDebug("All plugins installation completed");
700
701         //remove installation request
702         if (!PluginUtils::removeInstallationRequiredFlag()) {
703             LogInfo("Failed to remove file initializing plugin installation");
704         }
705
706         //remove lock file
707         if (!PluginUtils::unlockPluginInstallation()) {
708             LogInfo("Failed to remove installation lock");
709         }
710
711         if (This->popupsEnabled()) {
712             This->m_popup->init();
713             elm_progressbar_value_set(This->m_popup->m_progressbar, 100.0);
714             evas_object_show(This->m_popup->m_popup);
715         }
716
717         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
718             ::PostEvent(WRTInstallerNS::NextStepEvent());
719     } else {
720         if (This->popupsEnabled()) {
721             This->m_popup->init();
722             float percent = (This->m_totalPlugins - This->m_numPluginsToInstall)/(float)This->m_totalPlugins;
723             elm_progressbar_value_set(This->m_popup->m_progressbar, percent);
724             evas_object_show(This->m_popup->m_popup);
725         }
726
727         This->DPL::Event::ControllerEventHandler<WRTInstallerNS::InstallPluginEvent>::PostEvent(
728                 WRTInstallerNS::InstallPluginEvent());
729     }
730
731     if (WRT_SUCCESS == status) {
732         This->m_returnStatus = 0;
733         LogDebug("One plugin Installation succesfull: " << path);
734         return;
735     }
736
737     // Failure
738     LogWarning("One of the plugins installation failed!: " << path);
739
740     if (WRT_PLUGIN_INSTALLER_ERROR_WAITING == status) {
741         LogInfo("Plugin installation is waiting for dependencies");
742     }
743
744     switch (status) {
745     case WRT_PLUGIN_INSTALLER_ERROR_WRONG_PATH:
746         LogError("failed: wrong path to plugin directory\n");
747         break;
748
749     case WRT_PLUGIN_INSTALLER_ERROR_METAFILE:
750         LogError("failed: plugin metafile error\n");
751         break;
752
753     case WRT_PLUGIN_INSTALLER_ERROR_ALREADY_INSTALLED:
754         LogError("failed: plugin already installed\n");
755         break;
756
757     case WRT_PLUGIN_INSTALLER_ERROR_LIBRARY_ERROR:
758         LogError("failed: plugin library: missing symbols or structures\n");
759         break;
760
761     case WRT_PLUGIN_INSTALLER_ERROR_UNKNOWN:
762         LogError("failed: unknown error\n");
763         break;
764
765     default:
766         break;
767     }
768 }
769
770 void WrtInstaller::staticWrtPluginInstallProgressCb(float percent,
771                                                     const char* description,
772                                                     void* userdata)
773 {
774     PluginInstallerData* data = static_cast<PluginInstallerData*>(userdata);
775
776     std::string path = std::string(data->pluginPath);
777
778     LogInfo("Plugin Installation: " << path <<
779             " progress: " << percent <<
780             "description " << description);
781 }
782
783 void WrtInstaller::staticWrtInstallProgressCallback(float percent,
784         const char* description, void* userdata)
785 {
786     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
787     std::stringstream percentStr;
788     LogInfo(" progress: " << percent <<
789             " description: " << description);
790
791     if (This->popupsEnabled()) {
792         This->m_popup->init();
793         elm_progressbar_value_set(This->m_popup->m_progressbar, percent/100.0);
794         evas_object_show(This->m_popup->m_popup);
795     }
796 }
797 void WrtInstaller::staticWrtUninstallProgressCallback(float percent,
798         const char* description, void* userdata)
799 {
800     WrtInstaller *This = static_cast<WrtInstaller*>(userdata);
801     std::stringstream percentStr;
802     LogInfo(" progress: " << percent <<
803             " description: " << description);
804
805     if (This->popupsEnabled()) {
806         This->m_popup->init();
807         elm_progressbar_value_set(This->m_popup->m_progressbar, percent/100.0);
808         evas_object_show(This->m_popup->m_popup);
809     }
810 }
811
812 WrtInstaller::InstallerPopup::InstallerPopup() :
813     m_win(NULL),
814     m_popup(NULL),
815     m_progressbar(NULL)
816 {
817 }
818
819 WrtInstaller::InstallerPopup::~InstallerPopup()
820 {
821     LogDebug("App Finished");
822 }
823
824 void WrtInstaller::InstallerPopup::init()
825 {
826     LogDebug("Window Init");
827
828     if (m_win == NULL) {
829         // create window
830         m_win = createWin("wrt-installer");
831
832         // create popup
833         m_popup = elm_popup_add(m_win);
834
835         // create progressbar
836         m_progressbar = elm_progressbar_add(m_popup);
837         elm_object_style_set(m_progressbar, "list_progress");
838         elm_progressbar_horizontal_set(m_progressbar, EINA_TRUE);
839         evas_object_size_hint_align_set(m_progressbar, EVAS_HINT_FILL,
840             EVAS_HINT_FILL);
841         evas_object_size_hint_weight_set(m_progressbar, EVAS_HINT_EXPAND,
842             EVAS_HINT_EXPAND);
843         elm_object_content_set(m_popup, m_progressbar);
844         elm_progressbar_value_set(m_progressbar, 0.0);
845         evas_object_show(m_progressbar);
846
847         evas_object_show(m_popup);
848         evas_object_show(m_win);
849     }
850 }
851
852 Evas_Object* WrtInstaller::InstallerPopup::createWin(const char *name)
853 {
854     Evas_Object *win;
855     win = elm_win_add(NULL, name, ELM_WIN_DIALOG_BASIC);
856
857     int w, h;
858     if(!win)
859         return NULL;
860
861     elm_win_alpha_set(win, EINA_TRUE);
862     elm_win_title_set(win, name);
863     elm_win_borderless_set(win, EINA_TRUE);
864     elm_win_raise(win);
865
866     ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
867     evas_object_resize(win, w, h);
868     return win;
869 }
870
871 void WrtInstaller::InstallerPopup::showPopup(void* userdata,
872                                              const DPL::String& pkgMsg,
873                                              ShowResultCallback callback)
874 {
875     Evas_Object *btn;
876
877
878     LogDebug("Result Popup Created");
879     evas_object_del(m_popup);
880     m_popup = NULL;
881
882     m_popup = elm_popup_add(m_win);
883     if (!m_popup)
884         return;
885
886     btn = elm_button_add(m_popup);
887     if (!btn) {
888         evas_object_del(m_popup);
889         return;
890     }
891     elm_object_text_set(btn, "OK");
892     evas_object_smart_callback_add(btn, "clicked", callback, userdata);
893     elm_object_part_content_set(m_popup, "button1", btn);
894     elm_object_part_text_set(m_popup, "title,text", "RESULT");
895     elm_object_text_set(m_popup, DPL::ToUTF8String(pkgMsg).c_str());
896
897     evas_object_show(m_popup);
898     evas_object_show(m_win);
899
900 }
901
902 void WrtInstaller::showResultCallback(void *data, Evas_Object* /*obj*/,
903                                       void* /*event_info*/)
904 {
905     WrtInstaller *This = static_cast<WrtInstaller*>(data);
906     Assert(This);
907
908     This->DPL::Event::ControllerEventHandler<WRTInstallerNS::NextStepEvent>
909         ::PostEvent(WRTInstallerNS::NextStepEvent());
910 }
911
912 void WrtInstaller::failResultCallback(void *data, Evas_Object* /*obj*/,
913                                       void* /*event_info*/)
914 {
915     WrtInstaller *This = static_cast<WrtInstaller*>(data);
916     Assert(This);
917
918     This->DPL::Event::ControllerEventHandler<WRTInstallerNS::QuitEvent>
919         ::PostEvent(WRTInstallerNS::QuitEvent());
920 }
921
922 void WrtInstaller::installNewPlugins()
923 {
924     LogDebug("Install new plugins");
925
926     if (!PluginUtils::lockPluginInstallation()) {
927         LogInfo("Lock NOT created");
928         return;
929     }
930
931     if (!PluginUtils::checkPluginInstallationRequired()) {
932         LogDebug("Plugin installation not required");
933         PluginUtils::unlockPluginInstallation();
934         return;
935     }
936
937     m_startupPluginInstallation = true;
938     AddStep(&WrtInstaller::installPluginsStep);
939 }
940
941 bool WrtInstaller::popupsEnabled() const
942 {
943     return !m_quiet && !GlobalSettings::PopupsTestModeEnabled();
944 }
945
946 int main(int argc, char *argv[])
947 {
948     // Output on stdout will be flushed after every newline character,
949     // even if it is redirected to a pipe. This is useful for running
950     // from a script and parsing output.
951     // (Standard behavior of stdlib is to use full buffering when
952     // redirected to a pipe, which means even after an end of line
953     // the output may not be flushed).
954     setlinebuf(stdout);
955
956     // Check and re-set the file open limitation
957     struct rlimit rlim;
958     if (getrlimit(RLIMIT_NOFILE, &rlim) != -1) {
959         LogDebug("RLIMIT_NOFILE sft(" << rlim.rlim_cur << ")" );
960         LogDebug("RLIMIT_NOFILE hrd(" << rlim.rlim_max << ")" );
961
962         if (rlim.rlim_cur < NOFILE_CNT_FOR_INSTALLER) {
963             rlim.rlim_cur = NOFILE_CNT_FOR_INSTALLER;
964             rlim.rlim_max = NOFILE_CNT_FOR_INSTALLER;
965             if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
966                 LogError("setrlimit is fail!!");
967             }
968         }
969     } else {
970         LogError("getrlimit is fail!!");
971     }
972
973     // set evas backend type for emulator
974     // popup isn't showed in the emulator,
975     // if backend isn't set to SW backend
976     if (GlobalSettings::IsEmulator()) {
977         if (setenv("ELM_ENGINE", "x11", 1)) {
978             LogDebug("Enable backend");
979         }
980     }
981
982     WrtInstaller app(argc, argv);
983     int ret = app.Exec();
984     LogDebug("App returned: " << ret);
985     ret = app.getReturnStatus();
986     LogDebug("WrtInstaller returned: " << ret);
987     return ret;
988 }