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