From: Tomasz Iwanek Date: Tue, 27 Aug 2013 09:24:00 +0000 (+0200) Subject: JobWidgetInstall refactoring - TaskConfiguration X-Git-Tag: submit/tizen_2.2/20130927.091952^2~44 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=24590c9410abc652cc77bdb24f7e58b1a4687719;p=platform%2Fframework%2Fweb%2Fwrt-installer.git JobWidgetInstall refactoring - TaskConfiguration [Issue#] LINUXWRT-820 [Feature] Refactoring [Cause] There is too much logic in JobWidgetInstall [Solution] This commit just moves code of JobWIdgetInstall to TaskConfiguration. ALL OTHER CHANGES ARE MARKED as TODO (job_install_refactoring) and will be done later. Following changes to be do in next: - make proper steps in TaskConfiguration, - clean getInstallerSTruct in TaskConfiguration, - remove second parsing of config.xml, - refactor TaskUnzip leftovers, - fix TODOs in JobWidgetInstall context, - header clean up in TaskConfiguration, JobWidgetInstall, - (maybe) functions appendTaskList* shoule be refactored to seperate abstraction, Jobs now uses MutableTaskList and tasks can be appended in running state. There is no change in code because most of code uses installer context anyway. Two additional fields were temporary supplied to installer context: needEncryption and configureResult (those was internal variables in JobWidgetInstall). Failure task was moved to seperate file. [Verification] There was finally changed only few branches of code. Do following steps (this tests two extracted to install context variables): 1. run wrt-installer -p - plugins should be installed. 2. Get widegt with some files (prefer with dozens of file e.g. use some game) - install this widget and run it - success, - run wrt-installer -i again and run widget - success, - uninstall widget and isntall it again - widget should be runnign properly, 3. Get wigdet with encryption set (repeat steps from point 2.). 4. Get malformed zip file. - try to install and observe failure message: ## wrt-installer : installation has failed - invalid widget package [SCMRequest] This change requires: https://review.tizendev.org/gerrit/87851 Change-Id: Ib0abe152a1e524310692e213255a34c19cfb14e3 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb7e367..fb19a2c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,8 @@ SET(INSTALLER_SOURCES ${INSTALLER_JOBS}/widget_install/task_commons.cpp ${INSTALLER_JOBS}/widget_install/task_widget_config.cpp ${INSTALLER_JOBS}/widget_install/task_database.cpp + ${INSTALLER_JOBS}/widget_install/task_installer_fail.cpp + ${INSTALLER_JOBS}/widget_install/task_configuration.cpp ${INSTALLER_JOBS}/widget_install/ace_registration.cpp ${INSTALLER_JOBS}/widget_install/task_file_manipulation.cpp ${INSTALLER_JOBS}/widget_install/task_smack.cpp diff --git a/src/jobs/job.h b/src/jobs/job.h index 1050cbc..df81e5f 100644 --- a/src/jobs/job.h +++ b/src/jobs/job.h @@ -16,7 +16,7 @@ #ifndef INSTALLER_MODEL_H #define INSTALLER_MODEL_H -#include +#include namespace Jobs { class JobExceptionBase; @@ -33,7 +33,7 @@ enum InstallationType typedef int JobHandle; class Job : - public DPL::TaskList + public DPL::MutableTaskList { public: Job(InstallationType installType); diff --git a/src/jobs/widget_install/job_widget_install.cpp b/src/jobs/widget_install/job_widget_install.cpp index 4ae3856..53cf66b 100644 --- a/src/jobs/widget_install/job_widget_install.cpp +++ b/src/jobs/widget_install/job_widget_install.cpp @@ -20,7 +20,6 @@ * @version 1.0 * @brief Implementation file for main installer task */ -#include #include #include #include @@ -28,7 +27,6 @@ #include #include -#include #include #include #include @@ -71,6 +69,8 @@ #include #include #include +#include +#include #include #include @@ -80,89 +80,8 @@ using namespace WrtDB; using namespace Jobs::Exceptions; -namespace // anonymous -{ -const char * const CONFIG_XML = "config.xml"; -const char * const WITH_OSP_XML = "res/wgt/config.xml"; -const char * const OSP_MANIFEST_XML = "info/manifest.xml"; - -//allowed: a-z, A-Z, 0-9 -const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$"; -const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$"; -const size_t PACKAGE_ID_LENGTH = 10; - -static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption"; -static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable"; -static const DPL::String SETTING_VALUE_ENCRYPTION_DISABLE = L"disable"; -const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME = - L"install-location"; -const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT = - L"prefer-external"; - -const std::string XML_EXTENSION = ".xml"; - -bool hasExtension(const std::string& filename, const std::string& extension) -{ - LogDebug("Looking for extension " << extension << " in: " << filename); - size_t fileLen = filename.length(); - size_t extLen = extension.length(); - if (fileLen < extLen) { - LogError("Filename " << filename << " is shorter than extension " - << extension); - false; - } - return (0 == filename.compare(fileLen - extLen, extLen, extension)); -} -} // namespace anonymous - namespace Jobs { namespace WidgetInstall { -class InstallerTaskFail : - public DPL::TaskDecl -{ - private: - ConfigureResult m_result; - - void StepFail() - { - if (m_result == ConfigureResult::Failed_InvalidConfig) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, - "invalid config"); - } else if (m_result == ConfigureResult::Failed_OpenZipError) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::OpenZipFailed, - "can't open wgt file"); - } else if (m_result == ConfigureResult::Failed_UnzipError) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::ExtractFileFailed, - "can't extract wgt file"); - } else if (m_result == ConfigureResult::Failed_LowerVersion) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion, - "package version is lower than installed version"); - } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled, - "package is already installed"); - } else if (m_result == ConfigureResult::Failed_WidgetRunning) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, - "widget is running"); - } else if (m_result == ConfigureResult::Failed_DrmError) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::DrmDecryptFailed, - "drm failed"); - } else if (m_result == ConfigureResult::Failed_NotSupportRDSUpdate) { - ThrowMsg(Jobs::WidgetInstall::Exceptions::NotSupportRDSUpdate, - "RDS update failed"); - } else { - ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed, - "widget installation or update not allowed!"); - } - } - - public: - InstallerTaskFail(ConfigureResult result) : - DPL::TaskDecl(this), - m_result(result) - { - AddStep(&InstallerTaskFail::StepFail); - } -}; JobWidgetInstall::JobWidgetInstall( std::string const &widgetPath, @@ -173,572 +92,109 @@ JobWidgetInstall::JobWidgetInstall( m_exceptionCaught(Jobs::Exceptions::Success) { m_installerContext.mode = m_jobStruct.m_installMode; - ConfigureResult result = prepareInstallation(widgetPath); - - if (result == ConfigureResult::Ok) { - LogDebug("Configure installation succeeded"); - m_installerContext.job->SetProgressFlag(true); - - AddTask(new TaskRecovery(m_installerContext)); - - AddTask(new TaskWidgetConfig(m_installerContext)); - if (m_installerContext.widgetConfig.packagingType == - WrtDB::PKG_TYPE_HOSTED_WEB_APP) - { - AddTask(new TaskPrepareFiles(m_installerContext)); - } - AddTask(new TaskCertify(m_installerContext)); - AddTask(new TaskCertifyLevel(m_installerContext)); - if (m_needEncryption) { - AddTask(new TaskEncryptResource(m_installerContext)); - } - AddTask(new TaskFileManipulation(m_installerContext)); - AddTask(new TaskManifestFile(m_installerContext)); - if (m_installerContext.widgetConfig.packagingType == - PKG_TYPE_HYBRID_WEB_APP) - { - AddTask(new TaskInstallOspsvc(m_installerContext)); - } - AddTask(new TaskDatabase(m_installerContext)); - AddTask(new TaskAceCheck(m_installerContext)); - AddTask(new TaskSmack(m_installerContext)); - AddTask(new TaskPkgInfoUpdate(m_installerContext)); - } else if (result == ConfigureResult::Updated) { - LogDebug("Configure installation updated"); - LogDebug("Widget Update"); - m_installerContext.job->SetProgressFlag(true); - - if (m_installerContext.mode.command == - InstallMode::Command::REINSTALL) - { - AddTask(new TaskPrepareReinstall(m_installerContext)); - } - - AddTask(new TaskWidgetConfig(m_installerContext)); - - if (m_installerContext.widgetConfig.packagingType == - WrtDB::PKG_TYPE_HOSTED_WEB_APP) - { - AddTask(new TaskPrepareFiles(m_installerContext)); - } - - AddTask(new TaskCertify(m_installerContext)); - AddTask(new TaskCertifyLevel(m_installerContext)); - if (m_needEncryption) { - AddTask(new TaskEncryptResource(m_installerContext)); - } - if (m_installerContext.mode.extension != - InstallMode::ExtensionType::DIR) { - AddTask(new TaskUpdateFiles(m_installerContext)); - AddTask(new TaskFileManipulation(m_installerContext)); - } - - AddTask(new TaskManifestFile(m_installerContext)); - if (m_installerContext.widgetConfig.packagingType == - PKG_TYPE_HYBRID_WEB_APP) - { - AddTask(new TaskInstallOspsvc(m_installerContext)); - } - AddTask(new TaskDatabase(m_installerContext)); - AddTask(new TaskAceCheck(m_installerContext)); - //TODO: remove widgetHandle from this task and move before database task - // by now widget handle is needed in ace check - // Any error in acecheck while update will break widget - AddTask(new TaskSmack(m_installerContext)); - AddTask(new TaskRemoveBackupFiles(m_installerContext)); - AddTask(new TaskPkgInfoUpdate(m_installerContext)); - } else { - // Installation is not allowed to proceed due to widget update policy - LogWarning("Configure installation failed!"); - getInstallerStruct().pkgmgrInterface->sendSignal( - PKGMGR_START_KEY, - PKGMGR_START_INSTALL); - getInstallerStruct().pkgmgrInterface->sendSignal( - PKGMGR_PROGRESS_KEY, - PKGMGR_START_VALUE); - - AddTask(new InstallerTaskFail(result)); - } -} - -ConfigureResult JobWidgetInstall::prepareInstallation( - const std::string &widgetPath) -{ - ConfigureResult result; - m_needEncryption = false; - Try - { - std::string tempDir; - if (m_installerContext.mode.extension == InstallMode::ExtensionType::DIR) { - if (m_installerContext.mode.command == - InstallMode::Command::REINSTALL) { - std::ostringstream tempPathBuilder; - tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); - tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); - tempPathBuilder << "/"; - tempPathBuilder << widgetPath; - tempDir = tempPathBuilder.str();; - } else { - tempDir = widgetPath; - } - } else { - tempDir = - Jobs::WidgetInstall::createTempPath( - m_installerContext.mode.rootPath == - InstallMode::RootPath::RO); - WidgetUnzip wgtUnzip; - wgtUnzip.unzipWgtFile(widgetPath, tempDir); - } - - LogDebug("widgetPath:" << widgetPath); - LogDebug("tempPath:" << tempDir); - - m_installerContext.widgetConfig.packagingType = - checkPackageType(widgetPath, tempDir); - ConfigParserData configData = getWidgetDataFromXML( - widgetPath, - tempDir, - m_installerContext.widgetConfig.packagingType, - m_installerContext.mode.command == InstallMode::Command::REINSTALL); - LogDebug("widget packaging type : " << - m_installerContext.widgetConfig.packagingType.pkgType); - - setTizenId(configData); - setApplicationType(configData); - m_needEncryption = detectResourceEncryption(configData); - setInstallLocationType(configData); - m_installerContext.callerPkgId = - DPL::FromUTF8String(getInstallerStruct().pkgmgrInterface->getCallerId()); - LogDebug("Caller Package Id : " << m_installerContext.callerPkgId); - - // Configure installation - result = ConfigureInstallation(widgetPath, configData, tempDir); - getInstallerStruct().pkgmgrInterface->sendSignal( - PKGMGR_PROGRESS_KEY, - PKGMGR_START_VALUE); - } - Catch(Exceptions::OpenZipFailed) - { - LogError("Failed to unzip for widget"); - result = ConfigureResult::Failed_OpenZipError; - } - Catch(Exceptions::ExtractFileFailed) - { - LogError("Failed to unzip for widget"); - result = ConfigureResult::Failed_UnzipError; - } - Catch(Exceptions::DrmDecryptFailed) - { - LogError("Failed to unzip for widget"); - result = ConfigureResult::Failed_DrmError; - } - Catch(Exceptions::MissingConfig) - { - LogError("Failed to localize config.xml"); - result = ConfigureResult::Failed_InvalidConfig; - } - Catch(Exceptions::WidgetConfigFileInvalid) - { - LogError("Invalid configuration file"); - result = ConfigureResult::Failed_InvalidConfig; - } - Catch(DPL::Exception) - { - LogError("Unknown exception"); - result = ConfigureResult::Failed; - } - - return result; -} - -void JobWidgetInstall::setTizenId( - const WrtDB::ConfigParserData &configInfo) -{ - bool shouldMakeAppid = false; - using namespace PackageManager; - if (!!configInfo.tizenAppId) { - LogDebug("Setting tizenAppId provided in config.xml: " << - configInfo.tizenAppId); - - m_installerContext.widgetConfig.tzAppid = *configInfo.tizenAppId; - //check package id. - if (!!configInfo.tizenPkgId) { - LogDebug("Setting tizenPkgId provided in config.xml: " << - configInfo.tizenPkgId); - - m_installerContext.widgetConfig.tzPkgid = *configInfo.tizenPkgId; - } else { - DPL::String appid = *configInfo.tizenAppId; - if (appid.length() > PACKAGE_ID_LENGTH) { - m_installerContext.widgetConfig.tzPkgid = - appid.substr(0, PACKAGE_ID_LENGTH); - } else { - //old version appid only has 10byte random character is able to install for a while. - //this case appid equal pkgid. - m_installerContext.widgetConfig.tzPkgid = - *configInfo.tizenAppId; - shouldMakeAppid = true; - } - } - } else { - shouldMakeAppid = true; - TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId(); - LogDebug("Checking if pkg id is unique"); - while (true) { - if (!validateTizenPackageID(pkgId)) { - //path exist, chose another one - pkgId = WidgetDAOReadOnly::generatePkgId(); - continue; - } - break; - } - m_installerContext.widgetConfig.tzPkgid = pkgId; - LogDebug("tizen_id name was generated by WRT: " << - m_installerContext.widgetConfig.tzPkgid); - } - - if (shouldMakeAppid == true) { - DPL::OptionalString name; - DPL::OptionalString defaultLocale = configInfo.defaultlocale; - - FOREACH(localizedData, configInfo.localizedDataSet) - { - Locale i = localizedData->first; - if (!!defaultLocale) { - if (defaultLocale == i) { - name = localizedData->second.name; - break; - } - } else { - name = localizedData->second.name; - break; - } - } - regex_t regx; - if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { - LogDebug("Regcomp failed"); - } - - LogDebug("Name : " << name); - if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(), - static_cast(0), NULL, 0) != REG_NOERROR)) - { - // TODO : generate name move to wrt-commons - std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - std::ostringstream genName; - struct timeval tv; - gettimeofday(&tv, NULL); - unsigned int seed = time(NULL) + tv.tv_usec; - - genName << "_" << allowedString[rand_r(&seed) % allowedString.length()]; - name = DPL::FromUTF8String(genName.str()); - LogDebug("name was generated by WRT"); - } - regfree(®x); - LogDebug("Name : " << name); - std::ostringstream genid; - genid << m_installerContext.widgetConfig.tzPkgid << "." << name; - LogDebug("tizen appid was generated by WRT : " << genid.str()); - - DPL::OptionalString appid = DPL::FromUTF8String(genid.str()); - NormalizeAndTrimSpaceString(appid); - m_installerContext.widgetConfig.tzAppid = *appid; - } - - // send start signal of pkgmgr - getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String( - m_installerContext. - widgetConfig. - tzPkgid)); - LogDebug("Tizen App Id : " << m_installerContext.widgetConfig.tzAppid); - LogDebug("Tizen Pkg Id : " << m_installerContext.widgetConfig.tzPkgid); - LogDebug("W3C Widget GUID : " << m_installerContext.widgetConfig.guid); -} - -void JobWidgetInstall::configureWidgetLocation(const std::string & widgetPath, - const std::string& tempPath) -{ - m_installerContext.locations = - WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig. - tzPkgid), - widgetPath, tempPath, - m_installerContext.widgetConfig.packagingType, - m_installerContext.mode.rootPath == - InstallMode::RootPath::RO, - m_installerContext.mode.extension); - m_installerContext.locations->registerAppid( - DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid)); - - LogDebug("widgetSource " << widgetPath); -} + m_installerContext.requestedPath = widgetPath; -ConfigureResult JobWidgetInstall::ConfigureInstallation( - const std::string &widgetSource, - const WrtDB::ConfigParserData &configData, - const std::string &tempPath) -{ - ConfigureResult result = ConfigureResult::Failed; - WidgetUpdateInfo update; - - // checking installed web application - Try { - // checking existing application is installed - WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid); - // no excpetion means, it isn't update mode - getInstallerStruct().pkgmgrInterface->sendSignal( - PKGMGR_START_KEY, - PKGMGR_START_UPDATE); - - update = detectWidgetUpdate(configData, - m_installerContext.widgetConfig.tzAppid); - result = checkWidgetUpdate(update); - if (result != ConfigureResult::Updated) { - // Already installed TizenAppId. return failed - return ConfigureResult::Failed_AlreadyInstalled; - } - if (!checkSupportRDSUpdate(configData)) { - return ConfigureResult::Failed_NotSupportRDSUpdate; - } - m_installerContext.isUpdateMode = true; - } - Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { - getInstallerStruct().pkgmgrInterface->sendSignal( - PKGMGR_START_KEY, - PKGMGR_START_INSTALL); - result = ConfigureResult::Ok; - m_installerContext.isUpdateMode = false; - - if (!validateTizenApplicationID( - m_installerContext.widgetConfig.tzAppid)) - { - LogError("tizen application ID is already used"); - return ConfigureResult::Failed_InvalidConfig; - } - if (!validateTizenPackageID(m_installerContext.widgetConfig.tzPkgid)) { - LogError("tizen package ID is already used"); - return ConfigureResult::Failed_AlreadyInstalled; - } - } - - configureWidgetLocation(widgetSource, tempPath); + //start configuration of installation + AddTask(new TaskConfiguration(m_installerContext)); // Init installer context m_installerContext.installStep = InstallerContext::INSTALL_START; m_installerContext.job = this; m_installerContext.widgetConfig.shareHref = std::string(); - - return result; } -bool JobWidgetInstall::validateTizenApplicationID( - const WrtDB::TizenAppId &tizenAppId) +void JobWidgetInstall::appendNewInstallationTaskList() { - LogDebug("tizen application ID = [" << tizenAppId << "]"); + LogDebug("Configure installation succeeded"); + m_installerContext.job->SetProgressFlag(true); - regex_t reg; - if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { - LogDebug("Regcomp failed"); - } + AddTask(new TaskRecovery(m_installerContext)); - if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0) - == REG_NOMATCH) + AddTask(new TaskWidgetConfig(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) { - regfree(®); - return false; + AddTask(new TaskPrepareFiles(m_installerContext)); } - regfree(®); - return true; -} - -bool JobWidgetInstall::validateTizenPackageID( - const WrtDB::TizenPkgId &tizenPkgId) -{ - std::string pkgId = DPL::ToUTF8String(tizenPkgId); - - std::string installPath = - std::string(GlobalConfig::GetUserInstalledWidgetPath()) + - "/" + pkgId; - - struct stat dirStat; - if ((stat(installPath.c_str(), &dirStat) == 0)) + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + AddTask(new TaskFileManipulation(m_installerContext)); + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) { - return false; + AddTask(new TaskInstallOspsvc(m_installerContext)); } - return true; + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); } -ConfigureResult JobWidgetInstall::checkWidgetUpdate( - const WidgetUpdateInfo &update) +void JobWidgetInstall::appendUpdateInstallationTaskList() { - if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) { - return ConfigureResult::Failed; - } + LogDebug("Configure installation updated"); + LogDebug("Widget Update"); + m_installerContext.job->SetProgressFlag(true); - LogDebug("existing version = '" << update.existingVersion); - LogDebug("incoming version = '" << update.incomingVersion); - LogDebug("Tizen AppID = " << update.tzAppId); - - // Check running state - bool isRunning = false; - int ret = - app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(), - &isRunning); - if (APP_MANAGER_ERROR_NONE != ret) { - LogError("Fail to get running state"); - return ConfigureResult::Failed_WidgetRunning; + if (m_installerContext.mode.command == + InstallMode::Command::REINSTALL) + { + AddTask(new TaskPrepareReinstall(m_installerContext)); } - if (true == isRunning) { - // get app_context for running application - // app_context must be released with app_context_destroy - app_context_h appCtx = NULL; - ret = - app_manager_get_app_context( - DPL::ToUTF8String(update.tzAppId).c_str(), - &appCtx); - if (APP_MANAGER_ERROR_NONE != ret) { - LogError("Fail to get app_context"); - return ConfigureResult::Failed_WidgetRunning; - } + AddTask(new TaskWidgetConfig(m_installerContext)); - // terminate app_context_h - ret = app_manager_terminate_app(appCtx); - if (APP_MANAGER_ERROR_NONE != ret) { - LogError("Fail to terminate running application"); - app_context_destroy(appCtx); - return ConfigureResult::Failed_WidgetRunning; - } else { - app_context_destroy(appCtx); - // app_manager_terminate_app isn't sync API - // wait until application isn't running (50ms * 100) - bool isStillRunning = true; - int checkingloop = 100; - struct timespec duration = { 0, 50 * 1000 * 1000 }; - while (--checkingloop >= 0) { - nanosleep(&duration, NULL); - int ret = - app_manager_is_running( - DPL::ToUTF8String(update.tzAppId).c_str(), - &isStillRunning); - if (APP_MANAGER_ERROR_NONE != ret) { - LogError("Fail to get running state"); - return ConfigureResult::Failed_WidgetRunning; - } - if (!isStillRunning) { - break; - } - } - if (isStillRunning) { - LogError("Fail to terminate running application"); - return ConfigureResult::Failed_WidgetRunning; - } - LogDebug("terminate application"); - } + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + AddTask(new TaskPrepareFiles(m_installerContext)); } - m_installerContext.widgetConfig.tzAppid = update.tzAppId; + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } - if (!!update.existingVersion || - m_installerContext.mode.extension == + if (m_installerContext.mode.extension != InstallMode::ExtensionType::DIR) { - return ConfigureResult::Updated; + AddTask(new TaskUpdateFiles(m_installerContext)); + AddTask(new TaskFileManipulation(m_installerContext)); } - return ConfigureResult::Failed; -} - -ConfigParserData JobWidgetInstall::getWidgetDataFromXML( - const std::string &widgetSource, - const std::string &tempPath, - WrtDB::PackagingType pkgType, - bool isReinstall) -{ - // Parse config - ParserRunner parser; - ConfigParserData configInfo; - Try + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) { - if (pkgType == PKG_TYPE_HOSTED_WEB_APP) { - parser.Parse(widgetSource, - ElementParserPtr( - new RootParser(configInfo, - DPL::FromUTF32String( - L"widget")))); - } else { - std::string configFile; - configFile = tempPath + "/" + CONFIG_XML; - if (!WrtUtilFileExists(configFile)) { - configFile = tempPath + "/" + WITH_OSP_XML; - } - - if (isReinstall) { - // checking RDS data directory - if (access(configFile.c_str(), F_OK) != 0) { - std::string tzAppId = - widgetSource.substr(widgetSource.find_last_of("/")+1); - WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId))); - configFile = DPL::ToUTF8String(*dao.getWidgetInstalledPath()); - configFile += "/"; - configFile += WITH_OSP_XML; - } - } - - if(!DPL::Utils::Path(configFile).Exists()) - { - ThrowMsg(Exceptions::MissingConfig, "Config file not exists"); - } - - parser.Parse(configFile, - ElementParserPtr( - new RootParser(configInfo, - DPL:: - FromUTF32String( - L"widget")))); - } - } - Catch(ElementParser::Exception::ParseError) - { - LogError("Failed to parse config.xml file"); - return ConfigParserData(); - } - Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) - { - LogError("Failed to find installed widget - give proper tizenId"); - return ConfigParserData(); - } - Catch(Exceptions::WidgetConfigFileNotFound){ - LogError("Failed to find config.xml"); - return ConfigParserData(); + AddTask(new TaskInstallOspsvc(m_installerContext)); } - return configInfo; + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + //TODO: remove widgetHandle from this task and move before database task + // by now widget handle is needed in ace check + // Any error in acecheck while update will break widget + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskRemoveBackupFiles(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); } -WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate( - const ConfigParserData &configInfo, - const WrtDB::TizenAppId &tizenId) +void JobWidgetInstall::appendFailureTaskList() { - LogDebug("Checking up widget package for config.xml..."); - OptionalWidgetVersion incomingVersion; - - if (!configInfo.version.IsNull()) { - incomingVersion = - DPL::Optional( - WidgetVersion(*configInfo.version)); - } - - WidgetDAOReadOnly dao(tizenId); - - OptionalWidgetVersion optVersion; - DPL::OptionalString version = dao.getVersion(); - if (!version.IsNull()) { - optVersion = OptionalWidgetVersion(WidgetVersion(*version)); - } + // Installation is not allowed to proceed due to widget update policy + LogWarning("Configure installation failed!"); + getInstallerStruct().pkgmgrInterface->sendSignal( + PKGMGR_START_KEY, + PKGMGR_START_INSTALL); + getInstallerStruct().pkgmgrInterface->sendSignal( + PKGMGR_PROGRESS_KEY, + PKGMGR_START_VALUE); - return WidgetUpdateInfo( - dao.getTzAppId(), - optVersion, - incomingVersion); + AddTask(new InstallerTaskFail(m_installerContext.confResult)); } void JobWidgetInstall::SendProgress() @@ -904,118 +360,5 @@ void JobWidgetInstall::displayWidgetInfo() LogDebug(out.str()); } - -WrtDB::PackagingType JobWidgetInstall::checkPackageType( - const std::string &widgetSource, - const std::string &tempPath) -{ - if (hasExtension(widgetSource, XML_EXTENSION)) { - LogDebug("Hosted app installation"); - return PKG_TYPE_HOSTED_WEB_APP; - } - - std::string configFile = tempPath + "/" + OSP_MANIFEST_XML; - if (WrtUtilFileExists(configFile)) { - return PKG_TYPE_HYBRID_WEB_APP; - } - - return PKG_TYPE_NOMAL_WEB_APP; -} - -void JobWidgetInstall::setApplicationType( - const WrtDB::ConfigParserData &configInfo) -{ - AppType widgetAppType = APP_TYPE_UNKNOWN; - FOREACH(iterator, configInfo.nameSpaces) { - LogDebug("namespace = [" << *iterator << "]"); - - if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) { - if (widgetAppType != APP_TYPE_UNKNOWN && - widgetAppType != APP_TYPE_TIZENWEBAPP) - { - LogError("To many namespaces declared in configuration fileA."); - ThrowMsg(Exceptions::WidgetConfigFileInvalid, - "Config.xml has more than one valid namespace"); - } - widgetAppType = APP_TYPE_TIZENWEBAPP; - } else { - LogDebug("Namespace ignored."); - } - } - - m_installerContext.widgetConfig.webAppType = widgetAppType; - - LogDebug("type = [" << - m_installerContext.widgetConfig.webAppType.getApptypeToString() << - "]"); -} - -bool JobWidgetInstall::detectResourceEncryption( - const WrtDB::ConfigParserData &configData) -{ - FOREACH(it, configData.settingsList) - { - if (it->m_name == SETTING_VALUE_ENCRYPTION && - it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) - { - LogDebug("resource need encryption"); - return true; - } - } - return false; -} - -void JobWidgetInstall::setInstallLocationType( - const WrtDB::ConfigParserData & configData) -{ - m_installerContext.locationType = INSTALL_LOCATION_TYPE_NOMAL; - if (m_installerContext.mode.installTime != InstallMode::InstallTime::PRELOAD) { - FOREACH(it, configData.settingsList) { - if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME && - it->m_value == - SETTING_VALUE_INSTALLTOEXT_PREPER_EXT) - { - LogDebug("This widget will be installed to sd card"); - m_installerContext.locationType = - INSTALL_LOCATION_TYPE_EXTERNAL; - } - } - } -} - -bool JobWidgetInstall::checkSupportRDSUpdate(const WrtDB::ConfigParserData - &configInfo) -{ - if (m_installerContext.mode.command == - InstallMode::Command::REINSTALL) - { - DPL::String configValue = SETTING_VALUE_ENCRYPTION_DISABLE; - DPL::String dbValue = SETTING_VALUE_ENCRYPTION_DISABLE; - - WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid); - WrtDB::WidgetSettings widgetSettings; - dao.getWidgetSettings(widgetSettings); - - FOREACH(it, widgetSettings) { - if (it->settingName == SETTING_VALUE_ENCRYPTION) { - dbValue = it->settingValue; - } - } - - FOREACH(data, configInfo.settingsList) - { - if (data->m_name == SETTING_VALUE_ENCRYPTION) - { - configValue = data->m_value; - } - } - if (configValue != dbValue) { - LogError("Not Support RDS mode because of encryption setting"); - return false; - } - } - - return true; -} } //namespace WidgetInstall } //namespace Jobs diff --git a/src/jobs/widget_install/job_widget_install.h b/src/jobs/widget_install/job_widget_install.h index 1eebc7b..62f8c6c 100644 --- a/src/jobs/widget_install/job_widget_install.h +++ b/src/jobs/widget_install/job_widget_install.h @@ -23,34 +23,16 @@ #ifndef WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ #define WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ -#include -#include #include #include #include -#include -#include -#include #include "widget_installer_struct.h" +#include using namespace Jobs::Exceptions; namespace Jobs { namespace WidgetInstall { -enum class ConfigureResult -{ - Ok, - Updated, - Failed, - Failed_InvalidConfig, - Failed_LowerVersion, - Failed_AlreadyInstalled, - Failed_WidgetRunning, - Failed_DrmError, - Failed_NotSupportRDSUpdate, - Failed_OpenZipError, - Failed_UnzipError, -}; class JobWidgetInstall : public Job, @@ -61,41 +43,8 @@ class JobWidgetInstall : private: InstallerContext m_installerContext; - //TODO move it to base class of all jobs -> make it base template class?? Jobs::Exceptions::Type m_exceptionCaught; std::string m_exceptionMessage; - WidgetUpdateInfo m_widgetUpdateInfo; - bool m_needEncryption; - - ConfigureResult ConfigureInstallation(const std::string &widgetSource, - const WrtDB::ConfigParserData - &configData, - const std::string &tempPath); - static WrtDB::ConfigParserData getWidgetDataFromXML( - const std::string &widgetSource, - const std::string &tempPath, - WrtDB::PackagingType pkgType, - bool isReinstall); - static WidgetUpdateInfo detectWidgetUpdate( - const WrtDB::ConfigParserData &configInfo, - const WrtDB::TizenAppId &tizenId); - void setTizenId(const WrtDB::ConfigParserData &configInfo); - void displayWidgetInfo(); - void configureWidgetLocation(const std::string & widgetPath, - const std::string &tempPath); - - WrtDB::PackagingType checkPackageType( - const std::string &widgetSource, - const std::string &tempPath); - bool detectResourceEncryption(const WrtDB::ConfigParserData &configData); - void setInstallLocationType(const WrtDB::ConfigParserData - &configData); - ConfigureResult prepareInstallation(const std::string &widgetPath); - bool validateTizenApplicationID(const WrtDB::TizenAppId &tizenAppId); - bool validateTizenPackageID(const WrtDB::TizenPkgId &tizenPkgId); - ConfigureResult checkWidgetUpdate(const WidgetUpdateInfo &update); - void setApplicationType(const WrtDB::ConfigParserData &configInfo); - bool checkSupportRDSUpdate(const WrtDB::ConfigParserData &configInfo); public: /** @@ -109,7 +58,14 @@ class JobWidgetInstall : void SendFinishedSuccess(); void SendFinishedFailure(); void SendProgressIconPath(const std::string &path); + void SaveExceptionData(const Jobs::JobExceptionBase&); + void displayWidgetInfo(); + + //execution paths + void appendNewInstallationTaskList(); + void appendUpdateInstallationTaskList(); + void appendFailureTaskList(); }; } //namespace WidgetInstall } //namespace Jobs diff --git a/src/jobs/widget_install/task_configuration.cpp b/src/jobs/widget_install/task_configuration.cpp new file mode 100644 index 0000000..5bdae02 --- /dev/null +++ b/src/jobs/widget_install/task_configuration.cpp @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.cpp + * @version 1.0 + * @author Tomasz Iwanek + * @brief implementation file for configuration task + */ +#include "task_configuration.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" + +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const char* const CONFIG_XML = "config.xml"; +const char* const WITH_OSP_XML = "res/wgt/config.xml"; +const char* const OSP_MANIFEST_XML = "info/manifest.xml"; + +//allowed: a-z, A-Z, 0-9 +const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$"; +const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$"; +const size_t PACKAGE_ID_LENGTH = 10; + +static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption"; +static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable"; +static const DPL::String SETTING_VALUE_ENCRYPTION_DISABLE = L"disable"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME = + L"install-location"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT = + L"prefer-external"; + +const std::string XML_EXTENSION = ".xml"; + +bool hasExtension(const std::string& filename, const std::string& extension) +{ + LogDebug("Looking for extension " << extension << " in: " << filename); + size_t fileLen = filename.length(); + size_t extLen = extension.length(); + if (fileLen < extLen) { + LogError("Filename " << filename << " is shorter than extension " + << extension); + return false; + } + return (0 == filename.compare(fileLen - extLen, extLen, extension)); +} +} // namespace anonymous + +namespace Jobs { +namespace WidgetInstall { + +TaskConfiguration::TaskConfiguration(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_result(ConfigureResult::Unknown) +{ + AddStep(&TaskConfiguration::StartStep); + AddStep(&TaskConfiguration::PrepareInstallationStep); + AddStep(&TaskConfiguration::AppendTasklistStep); + AddStep(&TaskConfiguration::EndStep); +} + +void TaskConfiguration::StartStep() +{ + LogDebug("--------- : START ----------"); +} + +void TaskConfiguration::EndStep() +{ + LogDebug("--------- : END ----------"); +} + +void TaskConfiguration::AppendTasklistStep() +{ + // TODO: (job_install_refactoring) do not store config result anywhere + m_context.confResult = m_result; + + if (m_result == ConfigureResult::Ok) { + LogInfo("TaskConfiguration -> new installation task list"); + m_context.job->appendNewInstallationTaskList(); + } else if (m_result == ConfigureResult::Updated) { + LogInfo("TaskConfiguration -> update installation task list"); + m_context.job->appendUpdateInstallationTaskList(); + } else { + LogInfo("TaskConfiguration -> failure task list"); + m_context.job->appendFailureTaskList(); + } +} + +void TaskConfiguration::PrepareInstallationStep() +{ + // TODO: (job_install_refactoring) clean up this task + std::string widgetPath = m_context.requestedPath; + ConfigureResult result; + m_context.needEncryption = false; + Try + { + std::string tempDir; + if (m_context.mode.extension == InstallMode::ExtensionType::DIR) { + if (m_context.mode.command == + InstallMode::Command::REINSTALL) { + std::ostringstream tempPathBuilder; + tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); + tempPathBuilder << "/"; + tempPathBuilder << widgetPath; + tempDir = tempPathBuilder.str(); + } else { + tempDir = widgetPath; + } + } else { + tempDir = + Jobs::WidgetInstall::createTempPath( + m_context.mode.rootPath == + InstallMode::RootPath::RO); + WidgetUnzip wgtUnzip; + wgtUnzip.unzipWgtFile(widgetPath, tempDir); + } + + LogDebug("widgetPath:" << widgetPath); + LogDebug("tempPath:" << tempDir); + + m_context.widgetConfig.packagingType = + checkPackageType(widgetPath, tempDir); + ConfigParserData configData = getWidgetDataFromXML( + widgetPath, + tempDir, + m_context.widgetConfig.packagingType, + m_context.mode.command == InstallMode::Command::REINSTALL); + LogDebug("widget packaging type : " << + m_context.widgetConfig.packagingType.pkgType); + + setTizenId(configData); + setApplicationType(configData); + m_context.needEncryption = detectResourceEncryption(configData); + setInstallLocationType(configData); + // TODO: (job_install_refactoring) hide this call + m_context.callerPkgId = + DPL::FromUTF8String(m_context.job->getInstallerStruct().pkgmgrInterface->getCallerId()); + LogDebug("Caller Package Id : " << m_context.callerPkgId); + + // Configure installation + result = ConfigureInstallation(widgetPath, configData, tempDir); + // TODO: (job_install_refactoring) hide this call + m_context.job->getInstallerStruct().pkgmgrInterface->sendSignal( + PKGMGR_PROGRESS_KEY, + PKGMGR_START_VALUE); + } + Catch(Exceptions::OpenZipFailed) + { + LogError("Failed to unzip for widget"); + result = ConfigureResult::Failed_OpenZipError; + } + Catch(Exceptions::ExtractFileFailed) + { + LogError("Failed to unzip for widget"); + result = ConfigureResult::Failed_UnzipError; + } + Catch(Exceptions::DrmDecryptFailed) + { + LogError("Failed to unzip for widget"); + result = ConfigureResult::Failed_DrmError; + } + Catch(Exceptions::MissingConfig) + { + LogError("Failed to localize config.xml"); + result = ConfigureResult::Failed_InvalidConfig; + } + Catch(Exceptions::WidgetConfigFileInvalid) + { + LogError("Invalid configuration file"); + result = ConfigureResult::Failed_InvalidConfig; + } + Catch(DPL::Exception) + { + LogError("Unknown exception"); + result = ConfigureResult::Failed; + } + + m_result = result; +} + +void TaskConfiguration::setTizenId( + const WrtDB::ConfigParserData &configInfo) +{ + bool shouldMakeAppid = false; + using namespace PackageManager; + if (!!configInfo.tizenAppId) { + LogDebug("Setting tizenAppId provided in config.xml: " << + configInfo.tizenAppId); + + m_context.widgetConfig.tzAppid = *configInfo.tizenAppId; + //check package id. + if (!!configInfo.tizenPkgId) { + LogDebug("Setting tizenPkgId provided in config.xml: " << + configInfo.tizenPkgId); + + m_context.widgetConfig.tzPkgid = *configInfo.tizenPkgId; + } else { + DPL::String appid = *configInfo.tizenAppId; + if (appid.length() > PACKAGE_ID_LENGTH) { + m_context.widgetConfig.tzPkgid = + appid.substr(0, PACKAGE_ID_LENGTH); + } else { + //old version appid only has 10byte random character is able to install for a while. + //this case appid equal pkgid. + m_context.widgetConfig.tzPkgid = + *configInfo.tizenAppId; + shouldMakeAppid = true; + } + } + } else { + shouldMakeAppid = true; + TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId(); + LogDebug("Checking if pkg id is unique"); + while (true) { + if (!validateTizenPackageID(pkgId)) { + //path exist, chose another one + pkgId = WidgetDAOReadOnly::generatePkgId(); + continue; + } + break; + } + m_context.widgetConfig.tzPkgid = pkgId; + LogDebug("tizen_id name was generated by WRT: " << + m_context.widgetConfig.tzPkgid); + } + + if (shouldMakeAppid == true) { + DPL::OptionalString name; + DPL::OptionalString defaultLocale = configInfo.defaultlocale; + + FOREACH(localizedData, configInfo.localizedDataSet) + { + Locale i = localizedData->first; + if (!!defaultLocale) { + if (defaultLocale == i) { + name = localizedData->second.name; + break; + } + } else { + name = localizedData->second.name; + break; + } + } + regex_t regx; + if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + LogDebug("Regcomp failed"); + } + + LogDebug("Name : " << name); + if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(), + static_cast(0), NULL, 0) != REG_NOERROR)) + { + // TODO : (job_install_refactoring) generate name move to wrt-commons + std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + std::ostringstream genName; + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned int seed = time(NULL) + tv.tv_usec; + + genName << "_" << allowedString[rand_r(&seed) % allowedString.length()]; + name = DPL::FromUTF8String(genName.str()); + LogDebug("name was generated by WRT"); + } + regfree(®x); + LogDebug("Name : " << name); + std::ostringstream genid; + genid << m_context.widgetConfig.tzPkgid << "." << name; + LogDebug("tizen appid was generated by WRT : " << genid.str()); + + DPL::OptionalString appid = DPL::FromUTF8String(genid.str()); + NormalizeAndTrimSpaceString(appid); + m_context.widgetConfig.tzAppid = *appid; + } + + // send start signal of pkgmgr + // TODO: (job_install_refactoring) hide this call + m_context.job->getInstallerStruct().pkgmgrInterface->setPkgname(DPL::ToUTF8String( + m_context. + widgetConfig. + tzPkgid)); + LogDebug("Tizen App Id : " << m_context.widgetConfig.tzAppid); + LogDebug("Tizen Pkg Id : " << m_context.widgetConfig.tzPkgid); + LogDebug("W3C Widget GUID : " << m_context.widgetConfig.guid); +} + +void TaskConfiguration::configureWidgetLocation(const std::string & widgetPath, + const std::string& tempPath) +{ + m_context.locations = + WidgetLocation(DPL::ToUTF8String(m_context.widgetConfig. + tzPkgid), + widgetPath, tempPath, + m_context.widgetConfig.packagingType, + m_context.mode.rootPath == + InstallMode::RootPath::RO, + m_context.mode.extension); + m_context.locations->registerAppid( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid)); + + LogDebug("widgetSource " << widgetPath); +} + +ConfigureResult TaskConfiguration::ConfigureInstallation( + const std::string &widgetSource, + const WrtDB::ConfigParserData &configData, + const std::string &tempPath) +{ + ConfigureResult result = ConfigureResult::Failed; + WidgetUpdateInfo update; + + // checking installed web application + Try { + // checking existing application is installed + WidgetDAOReadOnly dao(m_context.widgetConfig.tzAppid); + // no excpetion means, it isn't update mode + // TODO: (job_install_refactoring) hide this call/ + m_context.job->getInstallerStruct().pkgmgrInterface->sendSignal( + PKGMGR_START_KEY, + PKGMGR_START_UPDATE); + + update = detectWidgetUpdate(configData, + m_context.widgetConfig.tzAppid); + result = checkWidgetUpdate(update); + if (result != ConfigureResult::Updated) { + // Already installed TizenAppId. return failed + return ConfigureResult::Failed_AlreadyInstalled; + } + if (!checkSupportRDSUpdate(configData)) { + return ConfigureResult::Failed_NotSupportRDSUpdate; + } + m_context.isUpdateMode = true; + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + // TODO: (job_install_refactoring) hide this call + m_context.job->getInstallerStruct().pkgmgrInterface->sendSignal( + PKGMGR_START_KEY, + PKGMGR_START_INSTALL); + result = ConfigureResult::Ok; + m_context.isUpdateMode = false; + + if (!validateTizenApplicationID( + m_context.widgetConfig.tzAppid)) + { + LogError("tizen application ID is already used"); + return ConfigureResult::Failed_InvalidConfig; + } + if (!validateTizenPackageID(m_context.widgetConfig.tzPkgid)) { + LogError("tizen package ID is already used"); + return ConfigureResult::Failed_AlreadyInstalled; + } + } + + configureWidgetLocation(widgetSource, tempPath); + + return result; +} + +bool TaskConfiguration::validateTizenApplicationID( + const WrtDB::TizenAppId &tizenAppId) +{ + LogDebug("tizen application ID = [" << tizenAppId << "]"); + + regex_t reg; + if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + LogDebug("Regcomp failed"); + } + + if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0) + == REG_NOMATCH) + { + regfree(®); + return false; + } + regfree(®); + return true; +} + +bool TaskConfiguration::validateTizenPackageID( + const WrtDB::TizenPkgId &tizenPkgId) +{ + std::string pkgId = DPL::ToUTF8String(tizenPkgId); + + std::string installPath = + std::string(GlobalConfig::GetUserInstalledWidgetPath()) + + "/" + pkgId; + + struct stat dirStat; + if ((stat(installPath.c_str(), &dirStat) == 0)) + { + return false; + } + return true; +} + +ConfigureResult TaskConfiguration::checkWidgetUpdate( + const WidgetUpdateInfo &update) +{ + if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) { + return ConfigureResult::Failed; + } + + LogDebug("existing version = '" << update.existingVersion); + LogDebug("incoming version = '" << update.incomingVersion); + LogDebug("Tizen AppID = " << update.tzAppId); + + // Check running state + bool isRunning = false; + int ret = + app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(), + &isRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + LogError("Fail to get running state"); + return ConfigureResult::Failed_WidgetRunning; + } + + if (true == isRunning) { + // get app_context for running application + // app_context must be released with app_context_destroy + app_context_h appCtx = NULL; + ret = + app_manager_get_app_context( + DPL::ToUTF8String(update.tzAppId).c_str(), + &appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + LogError("Fail to get app_context"); + return ConfigureResult::Failed_WidgetRunning; + } + + // terminate app_context_h + ret = app_manager_terminate_app(appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + LogError("Fail to terminate running application"); + app_context_destroy(appCtx); + return ConfigureResult::Failed_WidgetRunning; + } else { + app_context_destroy(appCtx); + // app_manager_terminate_app isn't sync API + // wait until application isn't running (50ms * 100) + bool isStillRunning = true; + int checkingloop = 100; + struct timespec duration = { 0, 50 * 1000 * 1000 }; + while (--checkingloop >= 0) { + nanosleep(&duration, NULL); + int ret = + app_manager_is_running( + DPL::ToUTF8String(update.tzAppId).c_str(), + &isStillRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + LogError("Fail to get running state"); + return ConfigureResult::Failed_WidgetRunning; + } + if (!isStillRunning) { + break; + } + } + if (isStillRunning) { + LogError("Fail to terminate running application"); + return ConfigureResult::Failed_WidgetRunning; + } + LogDebug("terminate application"); + } + } + + m_context.widgetConfig.tzAppid = update.tzAppId; + + if (!!update.existingVersion || + m_context.mode.extension == + InstallMode::ExtensionType::DIR) { + return ConfigureResult::Updated; + } + + return ConfigureResult::Failed; +} + +ConfigParserData TaskConfiguration::getWidgetDataFromXML( + const std::string &widgetSource, + const std::string &tempPath, + WrtDB::PackagingType pkgType, + bool isReinstall) +{ + // Parse config + ParserRunner parser; + ConfigParserData configInfo; + Try + { + if (pkgType == PKG_TYPE_HOSTED_WEB_APP) { + parser.Parse(widgetSource, + ElementParserPtr( + new RootParser(configInfo, + DPL::FromUTF32String( + L"widget")))); + } else { + std::string configFile; + configFile = tempPath + "/" + CONFIG_XML; + if (!WrtUtilFileExists(configFile)) { + configFile = tempPath + "/" + WITH_OSP_XML; + } + + if (isReinstall) { + // checking RDS data directory + if (access(configFile.c_str(), F_OK) != 0) { + std::string tzAppId = + widgetSource.substr(widgetSource.find_last_of("/")+1); + WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId))); + configFile = DPL::ToUTF8String(*dao.getWidgetInstalledPath()); + configFile += "/"; + configFile += WITH_OSP_XML; + } + } + + if(!DPL::Utils::Path(configFile).Exists()) + { + ThrowMsg(Exceptions::MissingConfig, "Config file not exists"); + } + + parser.Parse(configFile, + ElementParserPtr( + new RootParser(configInfo, + DPL:: + FromUTF32String( + L"widget")))); + } + } + Catch(ElementParser::Exception::ParseError) + { + LogError("Failed to parse config.xml file"); + return ConfigParserData(); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + LogError("Failed to find installed widget - give proper tizenId"); + return ConfigParserData(); + } + Catch(Exceptions::WidgetConfigFileNotFound){ + LogError("Failed to find config.xml"); + return ConfigParserData(); + } + + return configInfo; +} + +WidgetUpdateInfo TaskConfiguration::detectWidgetUpdate( + const ConfigParserData &configInfo, + const WrtDB::TizenAppId &tizenId) +{ + LogDebug("Checking up widget package for config.xml..."); + OptionalWidgetVersion incomingVersion; + + if (!configInfo.version.IsNull()) { + incomingVersion = + DPL::Optional( + WidgetVersion(*configInfo.version)); + } + + WidgetDAOReadOnly dao(tizenId); + + OptionalWidgetVersion optVersion; + DPL::OptionalString version = dao.getVersion(); + if (!version.IsNull()) { + optVersion = OptionalWidgetVersion(WidgetVersion(*version)); + } + + return WidgetUpdateInfo( + dao.getTzAppId(), + optVersion, + incomingVersion); +} + + +WrtDB::PackagingType TaskConfiguration::checkPackageType( + const std::string &widgetSource, + const std::string &tempPath) +{ + if (hasExtension(widgetSource, XML_EXTENSION)) { + LogDebug("Hosted app installation"); + return PKG_TYPE_HOSTED_WEB_APP; + } + + std::string configFile = tempPath + "/" + OSP_MANIFEST_XML; + if (WrtUtilFileExists(configFile)) { + return PKG_TYPE_HYBRID_WEB_APP; + } + + return PKG_TYPE_NOMAL_WEB_APP; +} + +void TaskConfiguration::setApplicationType( + const WrtDB::ConfigParserData &configInfo) +{ + AppType widgetAppType = APP_TYPE_UNKNOWN; + FOREACH(iterator, configInfo.nameSpaces) { + LogDebug("namespace = [" << *iterator << "]"); + + if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) { + if (widgetAppType != APP_TYPE_UNKNOWN && + widgetAppType != APP_TYPE_TIZENWEBAPP) + { + LogError("To many namespaces declared in configuration fileA."); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + "Config.xml has more than one valid namespace"); + } + widgetAppType = APP_TYPE_TIZENWEBAPP; + } else { + LogDebug("Namespace ignored."); + } + } + + m_context.widgetConfig.webAppType = widgetAppType; + + LogDebug("type = [" << + m_context.widgetConfig.webAppType.getApptypeToString() << + "]"); +} + +bool TaskConfiguration::detectResourceEncryption( + const WrtDB::ConfigParserData &configData) +{ + FOREACH(it, configData.settingsList) + { + if (it->m_name == SETTING_VALUE_ENCRYPTION && + it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) + { + LogDebug("resource need encryption"); + return true; + } + } + return false; +} + +void TaskConfiguration::setInstallLocationType( + const WrtDB::ConfigParserData & configData) +{ + m_context.locationType = INSTALL_LOCATION_TYPE_NOMAL; + if (m_context.mode.installTime != InstallMode::InstallTime::PRELOAD) { + FOREACH(it, configData.settingsList) { + if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME && + it->m_value == + SETTING_VALUE_INSTALLTOEXT_PREPER_EXT) + { + LogDebug("This widget will be installed to sd card"); + m_context.locationType = + INSTALL_LOCATION_TYPE_EXTERNAL; + } + } + } +} + +bool TaskConfiguration::checkSupportRDSUpdate(const WrtDB::ConfigParserData + &configInfo) +{ + if (m_context.mode.command == + InstallMode::Command::REINSTALL) + { + DPL::String configValue = SETTING_VALUE_ENCRYPTION_DISABLE; + DPL::String dbValue = SETTING_VALUE_ENCRYPTION_DISABLE; + + WidgetDAOReadOnly dao(m_context.widgetConfig.tzAppid); + WrtDB::WidgetSettings widgetSettings; + dao.getWidgetSettings(widgetSettings); + + FOREACH(it, widgetSettings) { + if (it->settingName == SETTING_VALUE_ENCRYPTION) { + dbValue = it->settingValue; + } + } + + FOREACH(data, configInfo.settingsList) + { + if (data->m_name == SETTING_VALUE_ENCRYPTION) + { + configValue = data->m_value; + } + } + if (configValue != dbValue) { + LogError("Not Support RDS mode because of encryption setting"); + return false; + } + } + + return true; +} + +} +} diff --git a/src/jobs/widget_install/task_configuration.h b/src/jobs/widget_install/task_configuration.h new file mode 100644 index 0000000..7f74410 --- /dev/null +++ b/src/jobs/widget_install/task_configuration.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.h + * @version 1.0 + * @author Tomasz Iwanek + * @brief header file for configuration task + */ +#ifndef TASK_CONFIGURATION_H +#define TASK_CONFIGURATION_H + +#include +#include + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { + +class TaskConfiguration : public DPL::TaskDecl +{ + InstallerContext& m_context; + ConfigureResult m_result; + WidgetUpdateInfo m_widgetUpdateInfo; + + ConfigureResult ConfigureInstallation(const std::string &widgetSource, + const WrtDB::ConfigParserData + &configData, + const std::string &tempPath); + static WrtDB::ConfigParserData getWidgetDataFromXML( + const std::string &widgetSource, + const std::string &tempPath, + WrtDB::PackagingType pkgType, + bool isReinstall); + static WidgetUpdateInfo detectWidgetUpdate( + const WrtDB::ConfigParserData &configInfo, + const WrtDB::TizenAppId &tizenId); + void setTizenId(const WrtDB::ConfigParserData &configInfo); + void configureWidgetLocation(const std::string & widgetPath, + const std::string &tempPath); + + WrtDB::PackagingType checkPackageType( + const std::string &widgetSource, + const std::string &tempPath); + bool detectResourceEncryption(const WrtDB::ConfigParserData &configData); + void setInstallLocationType(const WrtDB::ConfigParserData + &configData); + + bool validateTizenApplicationID(const WrtDB::TizenAppId &tizenAppId); + bool validateTizenPackageID(const WrtDB::TizenPkgId &tizenPkgId); + ConfigureResult checkWidgetUpdate(const WidgetUpdateInfo &update); + void setApplicationType(const WrtDB::ConfigParserData &configInfo); + bool checkSupportRDSUpdate(const WrtDB::ConfigParserData &configInfo); + + void PrepareInstallationStep(); + void AppendTasklistStep(); + + void StartStep(); + void EndStep(); + +public: + TaskConfiguration(InstallerContext& context); +}; + +} +} + +#endif // TASK_CONFIGURATION_H diff --git a/src/jobs/widget_install/task_installer_fail.cpp b/src/jobs/widget_install/task_installer_fail.cpp new file mode 100644 index 0000000..3cf73fc --- /dev/null +++ b/src/jobs/widget_install/task_installer_fail.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_installer_fail.cpp + * @version 1.0 + * @brief implementation file for failure task + */ +#include "task_installer_fail.h" + +#include + +using namespace WrtDB; +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { + +void InstallerTaskFail::StepFail() +{ + if (m_result == ConfigureResult::Failed_InvalidConfig) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, + "invalid config"); + } else if (m_result == ConfigureResult::Failed_OpenZipError) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::OpenZipFailed, + "can't open wgt file"); + } else if (m_result == ConfigureResult::Failed_UnzipError) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::ExtractFileFailed, + "can't extract wgt file"); + } else if (m_result == ConfigureResult::Failed_LowerVersion) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageLowerVersion, + "package version is lower than installed version"); + } else if (m_result == ConfigureResult::Failed_AlreadyInstalled) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled, + "package is already installed"); + } else if (m_result == ConfigureResult::Failed_WidgetRunning) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } else if (m_result == ConfigureResult::Failed_DrmError) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::DrmDecryptFailed, + "drm failed"); + } else if (m_result == ConfigureResult::Failed_NotSupportRDSUpdate) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::NotSupportRDSUpdate, + "RDS update failed"); + } else { + ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed, + "widget installation or update not allowed!"); + } +} + +InstallerTaskFail::InstallerTaskFail(ConfigureResult result) : + DPL::TaskDecl(this), + m_result(result) +{ + AddStep(&InstallerTaskFail::StepFail); +} + +} +} diff --git a/src/jobs/widget_install/task_installer_fail.h b/src/jobs/widget_install/task_installer_fail.h new file mode 100644 index 0000000..14fc7d0 --- /dev/null +++ b/src/jobs/widget_install/task_installer_fail.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_installer_fail.h + * @version 1.0 + * @brief header file for failure task + */ +#ifndef TASK_INSTALLER_FAIL_H +#define TASK_INSTALLER_FAIL_H + +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class InstallerTaskFail : + public DPL::TaskDecl +{ + private: + ConfigureResult m_result; + + void StepFail(); + + public: + InstallerTaskFail(ConfigureResult result); +}; + +} +} + +#endif // TASK_INSTALLER_FAIL_H diff --git a/src/jobs/widget_install/widget_install_context.h b/src/jobs/widget_install/widget_install_context.h index 0c118e9..a293b14 100644 --- a/src/jobs/widget_install/widget_install_context.h +++ b/src/jobs/widget_install/widget_install_context.h @@ -42,6 +42,23 @@ class WidgetModel; typedef std::map RequestedDevCapsMap; +//TODO: move it elsewhere +enum class ConfigureResult +{ + Ok, + Updated, + Failed, + Failed_InvalidConfig, + Failed_LowerVersion, + Failed_AlreadyInstalled, + Failed_WidgetRunning, + Failed_DrmError, + Failed_NotSupportRDSUpdate, + Failed_OpenZipError, + Failed_UnzipError, + Unknown +}; + struct InstallerContext { typedef enum InstallStepEnum @@ -98,6 +115,10 @@ struct InstallerContext bool isUpdateMode; InstallMode mode; DPL::String callerPkgId; + + std::string requestedPath; + bool needEncryption; // TODO: (job_install_refactoring) place into wisily not here + ConfigureResult confResult; //configuration result - TODO: (job_install_refactoring) get rid of this }; #endif // INSTALLER_CONTEXT_H