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