[Release] wrt-installer_0.1.37
[framework/web/wrt-installer.git] / src / jobs / widget_install / job_widget_install.cpp
index 4976db7..e2b2086 100644 (file)
@@ -69,8 +69,7 @@
 #include <widget_install/task_certificates.h>
 #include <widget_install/task_unzip.h>
 #include <widget_install/task_commons.h>
-
-#include <widget_install/task_plugins_copy.h>
+#include <widget_install/task_prepare_reinstall.h>
 
 #include <widget_install/widget_install_errors.h>
 #include <widget_install/widget_install_context.h>
@@ -92,7 +91,7 @@ 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";
 const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME =
-    L"install-location-type";
+    L"install-location";
 const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT =
     L"prefer-external";
 
@@ -195,12 +194,6 @@ JobWidgetInstall::JobWidgetInstall(
         }
 
         AddTask(new TaskFileManipulation(m_installerContext));
-        // TODO: Update progress information for this task
-
-        //This is sort of quick solution, because ACE verdicts are based upon
-        //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
-        //task.
-        AddTask(new TaskSmack(m_installerContext));
 
         AddTask(new TaskManifestFile(m_installerContext));
         if (m_installerContext.widgetConfig.packagingType ==
@@ -209,13 +202,20 @@ JobWidgetInstall::JobWidgetInstall(
             AddTask(new TaskInstallOspsvc(m_installerContext));
         }
         AddTask(new TaskCertificates(m_installerContext));
-        AddTask(new TaskPluginsCopy(m_installerContext));
         AddTask(new TaskDatabase(m_installerContext));
         AddTask(new TaskAceCheck(m_installerContext));
+        AddTask(new TaskSmack(m_installerContext));
     } else if (result == ConfigureResult::Updated) {
         LogInfo("Configure installation updated");
         LogInfo("Widget Update");
         m_installerContext.job->SetProgressFlag(true);
+
+        if (m_jobStruct.m_installMode ==
+            InstallMode::REINSTALL_MODE_DIRECTORY)
+        {
+            AddTask(new TaskPrepareReinstall(m_installerContext));
+        }
+
         if (m_installerContext.widgetConfig.packagingType !=
             WrtDB::PKG_TYPE_HOSTED_WEB_APP &&
             m_installerContext.widgetConfig.packagingType !=
@@ -244,9 +244,6 @@ JobWidgetInstall::JobWidgetInstall(
             AddTask(new TaskUpdateFiles(m_installerContext));
         }
 
-        /* TODO : To backup file, save md5 values */
-        AddTask(new TaskSmack(m_installerContext));
-
         AddTask(new TaskManifestFile(m_installerContext));
         if (m_installerContext.widgetConfig.packagingType ==
             PKG_TYPE_HYBRID_WEB_APP)
@@ -258,12 +255,12 @@ JobWidgetInstall::JobWidgetInstall(
         {
             AddTask(new TaskRemoveBackupFiles(m_installerContext));
         }
-        AddTask(new TaskPluginsCopy(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));
     } else if (result == ConfigureResult::Deferred) {
         // Installation is deferred
         LogInfo("Configure installation deferred");
@@ -288,8 +285,22 @@ ConfigureResult JobWidgetInstall::PrePareInstallation(
 
     Try
     {
-        std::string tempDir =
-            Jobs::WidgetInstall::createTempPath(m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_PRELOAD);
+        std::string tempDir;
+        if (m_jobStruct.m_installMode ==
+            InstallMode::REINSTALL_MODE_DIRECTORY)
+        {
+            std::ostringstream tempPathBuilder;
+            tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
+            tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath();
+            tempPathBuilder << "/";
+            tempPathBuilder << widgetPath;
+            tempDir = tempPathBuilder.str();;
+        } else {
+            tempDir =
+                Jobs::WidgetInstall::createTempPath(
+                        m_jobStruct.m_installMode ==
+                            InstallMode::INSTALL_MODE_PRELOAD);
+        }
 
         m_isDRM = isDRMWidget(widgetPath);
         if (true == m_isDRM) {
@@ -308,7 +319,9 @@ ConfigureResult JobWidgetInstall::PrePareInstallation(
                 widgetPath,
                 tempDir,
                 m_installerContext.widgetConfig.packagingType,
-                m_isDRM);
+                m_isDRM,
+                m_jobStruct.m_installMode ==
+                    InstallMode::REINSTALL_MODE_DIRECTORY);
         LogDebug("widget packaging type : " <<
                  m_installerContext.widgetConfig.packagingType.pkgType);
 
@@ -436,12 +449,24 @@ void JobWidgetInstall::setTizenId(
 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.locationType);
+    if (m_jobStruct.m_installMode ==
+         InstallMode::REINSTALL_MODE_DIRECTORY)
+    {
+        // replace widget path to installed path
+        m_installerContext.locations =
+            WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
+                                                 tzPkgid),
+                           widgetPath, tempPath,
+                           m_installerContext.widgetConfig.packagingType,
+                           m_installerContext.locationType);
+    } else {
+        m_installerContext.locations =
+            WidgetLocation(DPL::ToUTF8String(m_installerContext.widgetConfig.
+                                                 tzPkgid),
+                           widgetPath, tempPath,
+                           m_installerContext.widgetConfig.packagingType,
+                           m_installerContext.locationType);
+    }
     m_installerContext.locations->registerAppid(
         DPL::ToUTF8String(m_installerContext.widgetConfig.tzAppid));
 
@@ -550,20 +575,73 @@ ConfigureResult JobWidgetInstall::checkWidgetUpdate(
     LogInfo("incoming version = '" << update.incomingVersion);
     LogInfo("Tizen AppID = " << update.tzAppId);
 
+    if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) {
+        return ConfigureResult::Failed;
+    }
+
     // Check running state
     bool isRunning = false;
-    int retval =
+    int ret =
         app_manager_is_running(DPL::ToUTF8String(update.tzAppId).c_str(),
                                &isRunning);
-    if (APP_MANAGER_ERROR_NONE != retval || 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;
+            }
+            LogInfo("terminate application");
+        }
+    }
+
     m_installerContext.widgetConfig.tzAppid = update.tzAppId;
 
     if (isUpperVersion(update.existingVersion, update.incomingVersion) ||
-        m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY)
+        (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY) ||
+        (m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY))
     {
         LogInfo("Whether widget policy allow proceed ok");
         return ConfigureResult::Updated;
@@ -606,7 +684,8 @@ ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
     const std::string &widgetSource,
     const std::string &tempPath,
     WrtDB::PackagingType pkgType,
-    bool isDRM)
+    bool isDRM,
+    bool isReinstall)
 {
     // Parse config
     ParserRunner parser;
@@ -621,7 +700,23 @@ ConfigParserData JobWidgetInstall::getWidgetDataFromXML(
                                                           DPL::FromUTF32String(
                                                               L"widget"))));
         } else if (pkgType == PKG_TYPE_DIRECTORY_WEB_APP) {
-            parser.Parse(widgetSource + '/' + WITH_OSP_XML,
+            std::string configPath;
+            configPath = tempPath;
+            configPath += "/";
+            configPath += WITH_OSP_XML;
+
+            if (isReinstall) {
+                // checking RDS data directory
+                if (access(configPath.c_str(), F_OK) != 0) {
+                    std::string tzAppId =
+                        widgetSource.substr(widgetSource.find_last_of("/")+1);
+                    WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId(DPL::FromUTF8String(tzAppId)));
+                    configPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath());
+                    configPath += "/";
+                    configPath += WITH_OSP_XML;
+                }
+            }
+            parser.Parse(configPath,
                          ElementParserPtr(
                              new RootParser<WidgetParser>(
                                  configInfo,
@@ -716,9 +811,16 @@ WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
     }
 
     WidgetDAOReadOnly dao(tizenId);
+
+    OptionalWidgetVersion optVersion;
+    DPL::OptionalString version = dao.getVersion();
+    if (!version.IsNull()) {
+        optVersion = OptionalWidgetVersion(WidgetVersion(*version));
+    }
+
     return WidgetUpdateInfo(
         dao.getTzAppId(),
-        WidgetVersion(*dao.getVersion()),
+        optVersion,
         incomingVersion);
 }
 
@@ -891,7 +993,8 @@ WrtDB::PackagingType JobWidgetInstall::checkPackageType(
     const std::string &tempPath)
 {
     // Check installation type (direcotory/ or config.xml or widget.wgt)
-    if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY)
+    if (m_jobStruct.m_installMode == InstallMode::INSTALL_MODE_DIRECTORY ||
+         m_jobStruct.m_installMode == InstallMode::REINSTALL_MODE_DIRECTORY)
     {
         LogDebug("Install directly from directory");
         return PKG_TYPE_DIRECTORY_WEB_APP;
@@ -1055,7 +1158,7 @@ bool JobWidgetInstall::isDRMWidget(std::string /*widgetPath*/)
 bool JobWidgetInstall::DecryptDRMWidget(std::string /*widgetPath*/,
                                         std::string /*destPath*/)
 {
-    /* TODO */ 
+    /* TODO */
     return false;
 }
 } //namespace WidgetInstall