WAC code removal
[framework/web/wrt-installer.git] / src / jobs / widget_install / job_widget_install.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 /*
17  * @file    job_widget_install.cpp
18  * @author  Radoslaw Wicik r.wicik@samsung.com
19  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20  * @version 1.0
21  * @brief   Implementation file for main installer task
22  */
23 #include <memory>
24 #include <string>
25 #include <sys/time.h>
26 #include <ctime>
27 #include <cstdlib>
28 #include <limits.h>
29 #include <regex.h>
30
31 #include <dpl/noncopyable.h>
32 #include <dpl/abstract_waitable_input_adapter.h>
33 #include <dpl/abstract_waitable_output_adapter.h>
34 #include <dpl/zip_input.h>
35 #include <dpl/binary_queue.h>
36 #include <dpl/copy.h>
37 #include <dpl/assert.h>
38 #include <dpl/sstream.h>
39 #include <dpl/file_input.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/utils/path.h>
42 #include <dpl/wrt-dao-ro/common_dao_types.h>
43 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
44 #include <dpl/wrt-dao-ro/global_config.h>
45 #include <dpl/wrt-dao-ro/config_parser_data.h>
46 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
47 #include <dpl/localization/w3c_file_localization.h>
48
49 #include <libiriwrapper.h>
50 #include <pkg-manager/pkgmgr_signal.h>
51 #include <app_manager.h>
52
53 #include "root_parser.h"
54 #include "widget_parser.h"
55 #include "parser_runner.h"
56 #include <widget_install/job_widget_install.h>
57 #include <widget_install/task_certify.h>
58 #include <widget_install/task_widget_config.h>
59 #include <widget_install/task_file_manipulation.h>
60 #include <widget_install/task_ace_check.h>
61 #include <widget_install/task_smack.h>
62 #include <widget_install/task_manifest_file.h>
63 #include <widget_install/task_prepare_files.h>
64 #include <widget_install/task_recovery.h>
65 #include <widget_install/task_install_ospsvc.h>
66 #include <widget_install/task_update_files.h>
67 #include <widget_install/task_database.h>
68 #include <widget_install/task_remove_backup.h>
69 #include <widget_install/task_encrypt_resource.h>
70 #include <widget_install/task_certificates.h>
71 #include <widget_install/task_commons.h>
72 #include <widget_install/task_prepare_reinstall.h>
73
74 #include <widget_install/widget_install_errors.h>
75 #include <widget_install/widget_install_context.h>
76 #include <widget_install_to_external.h>
77 #include <widget_install/widget_unzip.h>
78
79 using namespace WrtDB;
80 using namespace Jobs::Exceptions;
81
82 namespace // anonymous
83 {
84 const char * const CONFIG_XML = "config.xml";
85 const char * const WITH_OSP_XML = "res/wgt/config.xml";
86 const char * const OSP_MANIFEST_XML = "info/manifest.xml";
87
88 //allowed: a-z, A-Z, 0-9
89 const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$";
90 const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$";
91 const size_t PACKAGE_ID_LENGTH = 10;
92
93 static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption";
94 static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable";
95 static const DPL::String SETTING_VALUE_ENCRYPTION_DISABLE = L"disable";
96 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
97     L"install-location";
98 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
99     L"prefer-external";
100
101 const std::string XML_EXTENSION = ".xml";
102
103 bool hasExtension(const std::string& filename, const std::string& extension)
104 {
105     LogDebug("Looking for extension " << extension << " in: " << filename);
106     size_t fileLen = filename.length();
107     size_t extLen = extension.length();
108     if (fileLen < extLen) {
109         LogError("Filename " << filename << " is shorter than extension "
110                              << extension);
111         return false;
112     }
113     return (0 == filename.compare(fileLen - extLen, extLen, extension));
114 }
115 } // namespace anonymous
116
117 namespace Jobs {
118 namespace WidgetInstall {
119 class InstallerTaskFail :
120     public DPL::TaskDecl<InstallerTaskFail>
121 {
122   private:
123     ConfigureResult m_result;
124
125     void StepFail()
126     {
127         if (m_result == ConfigureResult::Failed_InvalidConfig) {
128             ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid,
129                     "invalid config");
130         } else if (m_result == ConfigureResult::Failed_OpenZipError) {
131             ThrowMsg(Jobs::WidgetInstall::Exceptions::OpenZipFailed,
132                     "can't open wgt file");
133         } else if (m_result == ConfigureResult::Failed_UnzipError) {
134             ThrowMsg(Jobs::WidgetInstall::Exceptions::ExtractFileFailed,
135                     "can't extract wgt file");
136         } else if (m_result == ConfigureResult::Failed_LowerVersion) {
137             ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion,
138                     "package version is lower than installed version");
139         } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) {
140             ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled,
141                     "package is already installed");
142         } else if (m_result == ConfigureResult::Failed_WidgetRunning) {
143             ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError,
144                     "widget is running");
145         } else if (m_result == ConfigureResult::Failed_DrmError) {
146             ThrowMsg(Jobs::WidgetInstall::Exceptions::DrmDecryptFailed,
147                     "drm failed");
148         } else if (m_result == ConfigureResult::Failed_NotSupportRDSUpdate) {
149             ThrowMsg(Jobs::WidgetInstall::Exceptions::NotSupportRDSUpdate,
150                     "RDS update failed");
151         } else {
152             ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
153                     "widget installation or update not allowed!");
154         }
155     }
156
157   public:
158     InstallerTaskFail(ConfigureResult result) :
159         DPL::TaskDecl<InstallerTaskFail>(this),
160         m_result(result)
161     {
162         AddStep(&InstallerTaskFail::StepFail);
163     }
164 };
165
166 JobWidgetInstall::JobWidgetInstall(
167     std::string const &widgetPath,
168     const WidgetInstallationStruct &
169     installerStruct) :
170     Job(Installation),
171     JobContextBase<WidgetInstallationStruct>(installerStruct),
172     m_exceptionCaught(Jobs::Exceptions::Success)
173 {
174     m_installerContext.mode = m_jobStruct.m_installMode;
175     ConfigureResult result = prepareInstallation(widgetPath);
176
177     if (result == ConfigureResult::Ok) {
178         LogInfo("Configure installation succeeded");
179         m_installerContext.job->SetProgressFlag(true);
180
181         AddTask(new TaskRecovery(m_installerContext));
182
183         AddTask(new TaskWidgetConfig(m_installerContext));
184         if (m_installerContext.widgetConfig.packagingType ==
185             WrtDB::PKG_TYPE_HOSTED_WEB_APP)
186         {
187             AddTask(new TaskPrepareFiles(m_installerContext));
188         }
189         AddTask(new TaskCertify(m_installerContext));
190         if (m_needEncryption) {
191             AddTask(new TaskEncryptResource(m_installerContext));
192         }
193
194         AddTask(new TaskFileManipulation(m_installerContext));
195         AddTask(new TaskManifestFile(m_installerContext));
196         if (m_installerContext.widgetConfig.packagingType ==
197             PKG_TYPE_HYBRID_WEB_APP)
198         {
199             AddTask(new TaskInstallOspsvc(m_installerContext));
200         }
201         AddTask(new TaskCertificates(m_installerContext));
202         AddTask(new TaskDatabase(m_installerContext));
203         AddTask(new TaskAceCheck(m_installerContext));
204         AddTask(new TaskSmack(m_installerContext));
205     } else if (result == ConfigureResult::Updated) {
206         LogInfo("Configure installation updated");
207         LogInfo("Widget Update");
208         m_installerContext.job->SetProgressFlag(true);
209
210         if (m_installerContext.mode.command ==
211             InstallMode::Command::REINSTALL)
212         {
213             AddTask(new TaskPrepareReinstall(m_installerContext));
214         }
215
216         AddTask(new TaskWidgetConfig(m_installerContext));
217
218         if (m_installerContext.widgetConfig.packagingType ==
219             WrtDB::PKG_TYPE_HOSTED_WEB_APP)
220         {
221             AddTask(new TaskPrepareFiles(m_installerContext));
222         }
223
224         AddTask(new TaskCertify(m_installerContext));
225         if (m_needEncryption) {
226             AddTask(new TaskEncryptResource(m_installerContext));
227         }
228
229         if (m_installerContext.mode.extension !=
230                 InstallMode::ExtensionType::DIR) {
231             AddTask(new TaskUpdateFiles(m_installerContext));
232             AddTask(new TaskFileManipulation(m_installerContext));
233         }
234
235         AddTask(new TaskManifestFile(m_installerContext));
236         if (m_installerContext.widgetConfig.packagingType ==
237             PKG_TYPE_HYBRID_WEB_APP)
238         {
239             AddTask(new TaskInstallOspsvc(m_installerContext));
240         }
241         AddTask(new TaskCertificates(m_installerContext));
242         AddTask(new TaskDatabase(m_installerContext));
243         AddTask(new TaskAceCheck(m_installerContext));
244         //TODO: remove widgetHandle from this task and move before database task
245         // by now widget handle is needed in ace check
246         // Any error in acecheck while update will break widget
247         AddTask(new TaskSmack(m_installerContext));
248         AddTask(new TaskRemoveBackupFiles(m_installerContext));
249     } else {
250         // Installation is not allowed to proceed due to widget update policy
251         LogWarning("Configure installation failed!");
252
253         AddTask(new InstallerTaskFail(result));
254     }
255 }
256
257 ConfigureResult JobWidgetInstall::prepareInstallation(
258     const std::string &widgetPath)
259 {
260     ConfigureResult result;
261     m_needEncryption = false;
262
263     Try
264     {
265         std::string tempDir;
266         if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) {
267             if (m_installerContext.mode.command ==
268                     InstallMode::Command::REINSTALL) {
269                 std::ostringstream tempPathBuilder;
270                 tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
271                 tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
272                 tempPathBuilder << "/";
273                 tempPathBuilder << widgetPath;
274                 tempDir = tempPathBuilder.str();;
275             } else {
276                 tempDir = widgetPath;
277             }
278         } else {
279             tempDir =
280                 Jobs::WidgetInstall::createTempPath(
281                         m_installerContext.mode.rootPath ==
282                             InstallMode::RootPath::RO);
283             WidgetUnzip wgtUnzip;
284             wgtUnzip.unzipWgtFile(widgetPath, tempDir);
285         }
286
287         LogDebug("widgetPath:" << widgetPath);
288         LogDebug("tempPath:" << tempDir);
289
290         m_installerContext.widgetConfig.packagingType =
291             checkPackageType(widgetPath, tempDir);
292         ConfigParserData configData = getWidgetDataFromXML(
293                 widgetPath,
294                 tempDir,
295                 m_installerContext.widgetConfig.packagingType,
296                 m_installerContext.mode.command == InstallMode::Command::REINSTALL);
297         LogDebug("widget packaging type : " <<
298                  m_installerContext.widgetConfig.packagingType.pkgType);
299
300         setTizenId(configData);
301         setApplicationType(configData);
302         m_needEncryption = detectResourceEncryption(configData);
303         setInstallLocationType(configData);
304
305         // Configure installation
306         result = ConfigureInstallation(widgetPath, configData, tempDir);
307     }
308     Catch(Exceptions::OpenZipFailed)
309     {
310         LogError("Failed to unzip for widget");
311         result = ConfigureResult::Failed_OpenZipError;
312     }
313     Catch(Exceptions::ExtractFileFailed)
314     {
315         LogError("Failed to unzip for widget");
316         result = ConfigureResult::Failed_UnzipError;
317     }
318     Catch(Exceptions::DrmDecryptFailed)
319     {
320         LogError("Failed to unzip for widget");
321         result = ConfigureResult::Failed_DrmError;
322     }
323     Catch(Exceptions::MissingConfig)
324     {
325         LogError("Failed to localize config.xml");
326         result = ConfigureResult::Failed_InvalidConfig;
327     }
328     Catch(Exceptions::WidgetConfigFileInvalid)
329     {
330         LogError("Invalid configuration file");
331         result = ConfigureResult::Failed_InvalidConfig;
332     }
333     Catch(DPL::Exception)
334     {
335         LogError("Unknown exception");
336         result = ConfigureResult::Failed;
337     }
338
339     return result;
340 }
341
342 void JobWidgetInstall::setTizenId(
343     const WrtDB::ConfigParserData &configInfo)
344 {
345     bool shouldMakeAppid = false;
346     using namespace PackageManager;
347     if (!!configInfo.tizenAppId) {
348         LogDebug("Setting tizenAppId provided in config.xml: " <<
349                  configInfo.tizenAppId);
350
351         m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId;
352         //check package id.
353         if (!!configInfo.tizenPkgId) {
354             LogDebug("Setting tizenPkgId provided in config.xml: " <<
355                      configInfo.tizenPkgId);
356
357             m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId;
358         } else {
359             DPL::String appid = *configInfo.tizenAppId;
360             if (appid.length() > PACKAGE_ID_LENGTH) {
361                 m_installerContext.widgetConfig.tzPkgid =
362                     appid.substr(0, PACKAGE_ID_LENGTH);
363             } else {
364                 //old version appid only has 10byte random character is able to install for a while.
365                 //this case appid equal pkgid.
366                 m_installerContext.widgetConfig.tzPkgid =
367                     *configInfo.tizenAppId;
368                 shouldMakeAppid = true;
369             }
370         }
371     } else {
372         shouldMakeAppid = true;
373         TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId();
374         LogDebug("Checking if pkg id is unique");
375         while (true) {
376             if (!validateTizenPackageID(pkgId)) {
377                 //path exist, chose another one
378                 pkgId = WidgetDAOReadOnly::generatePkgId();
379                 continue;
380             }
381             break;
382         }
383         m_installerContext.widgetConfig.tzPkgid = pkgId;
384         LogInfo("tizen_id name was generated by WRT: " <<
385                 m_installerContext.widgetConfig.tzPkgid);
386     }
387
388     if (shouldMakeAppid == true) {
389         DPL::OptionalString name;
390         DPL::OptionalString defaultLocale = configInfo.defaultlocale;
391
392         FOREACH(localizedData, configInfo.localizedDataSet)
393         {
394             Locale i = localizedData->first;
395             if (!!defaultLocale) {
396                 if (defaultLocale == i) {
397                     name = localizedData->second.name;
398                     break;
399                 }
400             } else {
401                 name = localizedData->second.name;
402                 break;
403             }
404         }
405         regex_t regx;
406         if (regcomp(&regx, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
407             LogDebug("Regcomp failed");
408         }
409
410         LogDebug("Name : " << name);
411         if (!name || (regexec(&regx, DPL::ToUTF8String(*name).c_str(),
412                               static_cast<size_t>(0), NULL, 0) != REG_NOERROR))
413         {
414             // TODO : generate name move to wrt-commons
415             std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
416             std::ostringstream genName;
417             struct timeval tv;
418             gettimeofday(&tv, NULL);
419             unsigned int seed = time(NULL) + tv.tv_usec;
420
421             genName << "_" << allowedString[rand_r(&seed) % allowedString.length()];
422             name = DPL::FromUTF8String(genName.str());
423             LogDebug("name was generated by WRT");
424         }
425         regfree(&regx);
426         LogDebug("Name : " << name);
427         std::ostringstream genid;
428         genid << m_installerContext.widgetConfig.tzPkgid << "." << name;
429         LogDebug("tizen appid was generated by WRT : " << genid.str());
430
431         DPL::OptionalString appid = DPL::FromUTF8String(genid.str());
432         NormalizeAndTrimSpaceString(appid);
433         m_installerContext.widgetConfig.tzAppid = *appid;
434     }
435
436     // send start signal of pkgmgr
437     getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String(
438                                                          m_installerContext.
439                                                              widgetConfig.
440                                                              tzPkgid));
441     LogInfo("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid);
442     LogInfo("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid);
443     LogInfo("W3C Widget GUID : " << m_installerContext.widgetConfig.guid);
444 }
445
446 void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath,
447                                                const std::string& tempPath)
448 {
449     m_installerContext.locations =
450         WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
451                                              tzPkgid),
452                        widgetPath, tempPath,
453                        m_installerContext.widgetConfig.packagingType,
454                        m_installerContext.mode.rootPath ==
455                            InstallMode::RootPath::RO,
456                            m_installerContext.mode.extension);
457     m_installerContext.locations->registerAppid(
458         DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
459
460     LogInfo("widgetSource " << widgetPath);
461 }
462
463 ConfigureResult JobWidgetInstall::ConfigureInstallation(
464     const std::string &widgetSource,
465     const WrtDB::ConfigParserData &configData,
466     const std::string &tempPath)
467 {
468     ConfigureResult result = ConfigureResult::Failed;
469     WidgetUpdateInfo update;
470
471     // checking installed web application
472     Try {
473         // checking existing application is installed
474         WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
475         // no excpetion means, it isn't update mode
476         getInstallerStruct().pkgmgrInterface->sendSignal(
477                 PKGMGR_START_KEY,
478                 PKGMGR_START_UPDATE);
479
480         update = detectWidgetUpdate(configData,
481                                     m_installerContext.widgetConfig.tzAppid);
482         result = checkWidgetUpdate(update);
483         if (result != ConfigureResult::Updated) {
484             // Already installed TizenAppId. return failed
485             return ConfigureResult::Failed_AlreadyInstalled;
486         }
487         if (!checkSupportRDSUpdate(configData)) {
488             return ConfigureResult::Failed_NotSupportRDSUpdate;
489         }
490         m_installerContext.isUpdateMode = true;
491     }
492     Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
493         result = ConfigureResult::Ok;
494         getInstallerStruct().pkgmgrInterface->sendSignal(
495                 PKGMGR_START_KEY,
496                 PKGMGR_START_INSTALL);
497         m_installerContext.isUpdateMode = false;
498
499         if (!validateTizenApplicationID(
500             m_installerContext.widgetConfig.tzAppid))
501         {
502             LogError("tizen application ID is already used");
503             return ConfigureResult::Failed_InvalidConfig;
504         }
505         if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) {
506             LogError("tizen package ID is already used");
507             return ConfigureResult::Failed_AlreadyInstalled;
508         }
509     }
510
511     configureWidgetLocation(widgetSource, tempPath);
512
513     // Init installer context
514     m_installerContext.installStep = InstallerContext::INSTALL_START;
515     m_installerContext.job = this;
516     m_installerContext.widgetConfig.shareHref = std::string();
517
518     return result;
519 }
520
521 bool JobWidgetInstall::validateTizenApplicationID(
522     const WrtDB::TizenAppId &tizenAppId)
523 {
524     LogInfo("tizen application ID = [" << tizenAppId << "]");
525
526     regex_t reg;
527     if (regcomp(&reg, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
528         LogDebug("Regcomp failed");
529     }
530
531     if (regexec(&reg, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0)
532         == REG_NOMATCH)
533     {
534         regfree(&reg);
535         return false;
536     }
537     regfree(&reg);
538     return true;
539 }
540
541 bool JobWidgetInstall::validateTizenPackageID(
542     const WrtDB::TizenPkgId &tizenPkgId)
543 {
544     std::string pkgId = DPL::ToUTF8String(tizenPkgId);
545
546     std::string installPath =
547         std::string(GlobalConfig::GetUserInstalledWidgetPath()) +
548         "/" + pkgId;
549
550     struct stat dirStat;
551     if ((stat(installPath.c_str(), &dirStat) == 0))
552     {
553         return false;
554     }
555     return true;
556 }
557
558 ConfigureResult JobWidgetInstall::checkWidgetUpdate(
559     const WidgetUpdateInfo &update)
560 {
561     if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
562         return ConfigureResult::Failed;
563     }
564
565     LogInfo("existing version = '" << update.existingVersion);
566     LogInfo("incoming version = '" << update.incomingVersion);
567     LogInfo("Tizen AppID = " << update.tzAppId);
568
569     // Check running state
570     bool isRunning = false;
571     int ret =
572         app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
573                                &isRunning);
574     if (APP_MANAGER_ERROR_NONE != ret) {
575         LogError("Fail to get running state");
576         return ConfigureResult::Failed_WidgetRunning;
577     }
578
579     if (true == isRunning) {
580         // get app_context for running application
581         // app_context must be released with app_context_destroy
582         app_context_h appCtx = NULL;
583         ret =
584             app_manager_get_app_context(
585                 DPL::ToUTF8String(update.tzAppId).c_str(),
586                 &appCtx);
587         if (APP_MANAGER_ERROR_NONE != ret) {
588             LogError("Fail to get app_context");
589             return ConfigureResult::Failed_WidgetRunning;
590         }
591
592         // terminate app_context_h
593         ret = app_manager_terminate_app(appCtx);
594         if (APP_MANAGER_ERROR_NONE != ret) {
595             LogError("Fail to terminate running application");
596             app_context_destroy(appCtx);
597             return ConfigureResult::Failed_WidgetRunning;
598         } else {
599             app_context_destroy(appCtx);
600             // app_manager_terminate_app isn't sync API
601             // wait until application isn't running (50ms * 100)
602             bool isStillRunning = true;
603             int checkingloop = 100;
604             struct timespec duration = { 0, 50 * 1000 * 1000 };
605             while (--checkingloop >= 0) {
606                 nanosleep(&duration, NULL);
607                 int ret =
608                     app_manager_is_running(
609                         DPL::ToUTF8String(update.tzAppId).c_str(),
610                         &isStillRunning);
611                 if (APP_MANAGER_ERROR_NONE != ret) {
612                     LogError("Fail to get running state");
613                     return ConfigureResult::Failed_WidgetRunning;
614                 }
615                 if (!isStillRunning) {
616                     break;
617                 }
618             }
619             if (isStillRunning) {
620                 LogError("Fail to terminate running application");
621                 return ConfigureResult::Failed_WidgetRunning;
622             }
623             LogInfo("terminate application");
624         }
625     }
626
627     m_installerContext.widgetConfig.tzAppid = update.tzAppId;
628
629     if (!!update.existingVersion ||
630             m_installerContext.mode.extension ==
631             InstallMode::ExtensionType::DIR) {
632         return ConfigureResult::Updated;
633     }
634
635     return ConfigureResult::Failed;
636 }
637
638 ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
639     const std::string &widgetSource,
640     const std::string &tempPath,
641     WrtDB::PackagingType pkgType,
642     bool isReinstall)
643 {
644     // Parse config
645     ParserRunner parser;
646     ConfigParserData configInfo;
647     Try
648     {
649         if (pkgType == PKG_TYPE_HOSTED_WEB_APP) {
650             parser.Parse(widgetSource,
651                          ElementParserPtr(
652                              new RootParser<WidgetParser>(configInfo,
653                                                           DPL::FromUTF32String(
654                                                               L"widget"))));
655         } else {
656             std::string configFile;
657             configFile = tempPath + "/" + CONFIG_XML;
658             if (!WrtUtilFileExists(configFile)) {
659                 configFile = tempPath + "/" + WITH_OSP_XML;
660             }
661
662             if (isReinstall) {
663                 // checking RDS data directory
664                 if (access(configFile.c_str(), F_OK) != 0) {
665                     std::string tzAppId =
666                         widgetSource.substr(widgetSource.find_last_of("/")+1);
667                     WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
668                     configFile = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
669                     configFile += "/";
670                     configFile += WITH_OSP_XML;
671                 }
672             }
673
674             if(!DPL::Utils::Path(configFile).Exists())
675             {
676                 ThrowMsg(Exceptions::MissingConfig, "Config file not exists");
677             }
678
679             parser.Parse(configFile,
680                     ElementParserPtr(
681                         new RootParser<WidgetParser>(configInfo,
682                             DPL::
683                             FromUTF32String(
684                                 L"widget"))));
685         }
686     }
687     Catch(ElementParser::Exception::ParseError)
688     {
689         LogError("Failed to parse config.xml file");
690         return ConfigParserData();
691     }
692     Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
693     {
694         LogError("Failed to find installed widget - give proper tizenId");
695         return ConfigParserData();
696     }
697     Catch(Exceptions::WidgetConfigFileNotFound){
698         LogError("Failed to find config.xml");
699         return ConfigParserData();
700     }
701
702     return configInfo;
703 }
704
705 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
706     const ConfigParserData &configInfo,
707     const WrtDB::TizenAppId &tizenId)
708 {
709     LogInfo("Checking up widget package for config.xml...");
710     OptionalWidgetVersion incomingVersion;
711
712     if (!configInfo.version.IsNull()) {
713         incomingVersion =
714             DPL::Optional<WidgetVersion>(
715                 WidgetVersion(*configInfo.version));
716     }
717
718     WidgetDAOReadOnly dao(tizenId);
719
720     OptionalWidgetVersion optVersion;
721     DPL::OptionalString version = dao.getVersion();
722     if (!version.IsNull()) {
723         optVersion = OptionalWidgetVersion(WidgetVersion(*version));
724     }
725
726     return WidgetUpdateInfo(
727         dao.getTzAppId(),
728         optVersion,
729         incomingVersion);
730 }
731
732 void JobWidgetInstall::SendProgress()
733 {
734     using namespace PackageManager;
735     if (GetProgressFlag() != false) {
736         if (getInstallerStruct().progressCallback != NULL) {
737             // send progress signal of pkgmgr
738             std::ostringstream percent;
739             percent << static_cast<int>(GetProgressPercent());
740             getInstallerStruct().pkgmgrInterface->sendSignal(
741                 PKGMGR_PROGRESS_KEY,
742                 percent.str());
743
744             LogDebug("Call widget install progressCallbak");
745             getInstallerStruct().progressCallback(
746                 getInstallerStruct().userParam,
747                 GetProgressPercent(),
748                 GetProgressDescription());
749         }
750     }
751 }
752
753 void JobWidgetInstall::SendProgressIconPath(const std::string &path)
754 {
755     using namespace PackageManager;
756     if (GetProgressFlag() != false) {
757         if (getInstallerStruct().progressCallback != NULL) {
758             // send progress signal of pkgmgr
759             getInstallerStruct().pkgmgrInterface->sendSignal(
760                 PKGMGR_ICON_PATH,
761                 path);
762         }
763     }
764 }
765
766 void JobWidgetInstall::SendFinishedSuccess()
767 {
768     using namespace PackageManager;
769     // TODO : sync should move to separate task.
770     sync();
771
772     if (INSTALL_LOCATION_TYPE_EXTERNAL == m_installerContext.locationType) {
773         if (m_installerContext.isUpdateMode) {
774             WidgetInstallToExtSingleton::Instance().postUpgrade(true);
775         } else {
776             WidgetInstallToExtSingleton::Instance().postInstallation(true);
777         }
778         WidgetInstallToExtSingleton::Instance().deinitialize();
779     }
780
781     // remove widget install information file
782     unlink(m_installerContext.installInfo.c_str());
783
784     //inform widget info
785     JobWidgetInstall::displayWidgetInfo();
786
787     TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid;
788
789     // send signal of pkgmgr
790     getInstallerStruct().pkgmgrInterface->sendSignal(
791         PKGMGR_END_KEY,
792         PKGMGR_END_SUCCESS);
793
794     LogDebug("Call widget install successfinishedCallback");
795     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
796                                           DPL::ToUTF8String(
797                                               tizenId), Jobs::Exceptions::Success);
798 }
799
800 void JobWidgetInstall::SendFinishedFailure()
801 {
802     using namespace PackageManager;
803     // remove widget install information file
804     unlink(m_installerContext.installInfo.c_str());
805
806     LogError("Error number: " << m_exceptionCaught);
807     LogError("Message: " << m_exceptionMessage);
808     TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid;
809
810     LogDebug("Call widget install failure finishedCallback");
811     std::stringstream errorNum;
812     errorNum << m_exceptionCaught;
813
814     // send signal of pkgmgr
815     getInstallerStruct().pkgmgrInterface->sendSignal(
816         PKGMGR_ERROR,
817         errorNum.str());
818
819     getInstallerStruct().pkgmgrInterface->sendSignal(
820         PKGMGR_END_KEY,
821         PKGMGR_END_FAILURE);
822
823     getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
824                                           DPL::ToUTF8String(
825                                               tizenId), m_exceptionCaught);
826 }
827
828 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
829 {
830     m_exceptionCaught = static_cast<Jobs::Exceptions::Type>(e.getParam());
831     m_exceptionMessage = e.GetMessage();
832 }
833
834 void JobWidgetInstall::displayWidgetInfo()
835 {
836     WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
837
838     std::ostringstream out;
839     WidgetLocalizedInfo localizedInfo =
840         W3CFileLocalization::getLocalizedInfo(dao.getTzAppId());
841
842     out << std::endl <<
843     "===================================== INSTALLED WIDGET INFO =========" \
844     "============================";
845     out << std::endl << "Name:                        " << localizedInfo.name;
846     out << std::endl << "AppId:                     " << dao.getTzAppId();
847     WidgetSize size = dao.getPreferredSize();
848     out << std::endl << "Width:                       " << size.width;
849     out << std::endl << "Height:                      " << size.height;
850     out << std::endl << "Start File:                  " <<
851     W3CFileLocalization::getStartFile(dao.getTzAppId());
852     out << std::endl << "Version:                     " << dao.getVersion();
853     out << std::endl << "Licence:                     " <<
854     localizedInfo.license;
855     out << std::endl << "Licence Href:                " <<
856     localizedInfo.licenseHref;
857     out << std::endl << "Description:                 " <<
858     localizedInfo.description;
859     out << std::endl << "Widget Id:                   " << dao.getGUID();
860     out << std::endl << "Widget recognized:           " << dao.isRecognized();
861     out << std::endl << "Widget distributor signed:   " <<
862     dao.isDistributorSigned();
863     out << std::endl << "Widget trusted:              " << dao.isTrusted();
864
865     OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId());
866     DPL::OptionalString iconSrc =
867         !!icon ? icon->src : DPL::OptionalString::Null;
868     out << std::endl << "Icon:                        " << iconSrc;
869
870     out << std::endl << "Preferences:";
871     {
872         PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
873         FOREACH(it, list)
874         {
875             out << std::endl << "  Key:                       " <<
876             it->key_name;
877             out << std::endl << "      Readonly:              " <<
878             it->readonly;
879         }
880     }
881
882     out << std::endl << "Features:";
883     {
884         WidgetFeatureSet list = dao.getFeaturesList();
885         FOREACH(it, list)
886         {
887             out << std::endl << "  Name:                      " << it->name;
888         }
889     }
890
891     out << std::endl;
892
893     LogInfo(out.str());
894 }
895
896 WrtDB::PackagingType JobWidgetInstall::checkPackageType(
897     const std::string &widgetSource,
898     const std::string &tempPath)
899 {
900     if (hasExtension(widgetSource, XML_EXTENSION)) {
901         LogInfo("Hosted app installation");
902         return PKG_TYPE_HOSTED_WEB_APP;
903     }
904
905     std::string configFile = tempPath + "/" + OSP_MANIFEST_XML;
906     if (WrtUtilFileExists(configFile)) {
907         return PKG_TYPE_HYBRID_WEB_APP;
908     }
909
910     return PKG_TYPE_NOMAL_WEB_APP;
911 }
912
913 void JobWidgetInstall::setApplicationType(
914     const WrtDB::ConfigParserData &configInfo)
915 {
916     AppType widgetAppType = APP_TYPE_UNKNOWN;
917     FOREACH(iterator, configInfo.nameSpaces) {
918         LogInfo("namespace = [" << *iterator << "]");
919
920         if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) {
921             if (widgetAppType != APP_TYPE_UNKNOWN &&
922                 widgetAppType != APP_TYPE_TIZENWEBAPP)
923             {
924                 LogError("To many namespaces declared in configuration fileA.");
925                 ThrowMsg(Exceptions::WidgetConfigFileInvalid,
926                          "Config.xml has more than one valid namespace");
927             }
928             widgetAppType = APP_TYPE_TIZENWEBAPP;
929         } else {
930             LogDebug("Namespace ignored.");
931         }
932     }
933
934     m_installerContext.widgetConfig.webAppType = widgetAppType;
935
936     LogInfo("type = [" <<
937             m_installerContext.widgetConfig.webAppType.getApptypeToString() <<
938             "]");
939 }
940
941 bool JobWidgetInstall::detectResourceEncryption(
942     const WrtDB::ConfigParserData &configData)
943 {
944     FOREACH(it, configData.settingsList)
945     {
946         if (it->m_name == SETTING_VALUE_ENCRYPTION &&
947             it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE)
948         {
949             LogDebug("resource need encryption");
950             return true;
951         }
952     }
953     return false;
954 }
955
956 void JobWidgetInstall::setInstallLocationType(
957     const WrtDB::ConfigParserData & configData)
958 {
959     m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL;
960     if (m_installerContext.mode.installTime != InstallMode::InstallTime::PRELOAD) {
961         FOREACH(it, configData.settingsList) {
962             if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME &&
963                 it->m_value ==
964                 SETTING_VALUE_INSTALLTOEXT_PREPER_EXT)
965             {
966                 LogDebug("This widget will be installed to sd card");
967                 m_installerContext.locationType =
968                     INSTALL_LOCATION_TYPE_EXTERNAL;
969             }
970         }
971     }
972 }
973
974 bool JobWidgetInstall::checkSupportRDSUpdate(const WrtDB::ConfigParserData
975         &configInfo)
976 {
977     if (m_installerContext.mode.command ==
978             InstallMode::Command::REINSTALL)
979     {
980         DPL::String configValue = SETTING_VALUE_ENCRYPTION_DISABLE;
981         DPL::String dbValue = SETTING_VALUE_ENCRYPTION_DISABLE;
982
983         WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid);
984         WrtDB::WidgetSettings widgetSettings;
985         dao.getWidgetSettings(widgetSettings);
986
987         FOREACH(it, widgetSettings) {
988             if (it->settingName == SETTING_VALUE_ENCRYPTION) {
989                 dbValue = it->settingValue;
990             }
991         }
992
993         FOREACH(data, configInfo.settingsList)
994         {
995             if (data->m_name == SETTING_VALUE_ENCRYPTION)
996             {
997                 configValue = data->m_value;
998             }
999         }
1000         if (configValue != dbValue) {
1001             LogError("Not Support RDS mode because of encryption setting");
1002             return false;
1003         }
1004     }
1005
1006     return true;
1007 }
1008 } //namespace WidgetInstall
1009 } //namespace Jobs