tizen 2.4 release
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_database.cpp
similarity index 53%
rename from src_wearable/jobs/widget_install/task_database.cpp
rename to src/jobs/widget_install/task_database.cpp
index 8b9660b..39cde8c 100755 (executable)
 #include <cstdio>
 #include <time.h>
 #include <sys/stat.h>
+#include <sqlite3.h>
+#include <db-util.h>
 #include <widget_install/task_database.h>
-#include <widget_install/job_widget_install.h>
 #include <widget_install/widget_install_errors.h>
 #include <widget_install/widget_install_context.h>
-#ifdef DBOX_ENABLED
-#include <web_provider_livebox_info.h>
+#if USE(WEB_PROVIDER)
+#include <web_provider_widget_info.h>
 #endif
 #include <dpl/wrt-dao-rw/widget_dao.h>
+#include <dpl/log/log.h>
 #include <dpl/foreach.h>
-#include <dpl/utils/wrt_utility.h>
 #include <dpl/assert.h>
+#include <dpl/platform.h>
 #include <wrt-commons/security-origin-dao/security_origin_dao.h>
 #include <wrt-commons/widget-interface-dao/widget_interface_dao.h>
 #include <dpl/wrt-dao-ro/global_config.h>
 #include <dpl/wrt-dao-ro/widget_dao_types.h>
+#include <dpl/wrt-dao-ro/WrtDatabase.h>
 #include <string>
 #include <sstream>
-#include <ace_api_install.h>
-#include <ace_registration.h>
 #include <errno.h>
 #include <string.h>
 #include <map>
-#include <installer_log.h>
+#include <boost/filesystem.hpp>
+#include <dpl/log/secure_log.h>
 
 using namespace WrtDB;
+namespace bf = boost::filesystem;
 
 namespace Jobs {
 namespace WidgetInstall {
-TaskDatabase::TaskDatabase(InstallerContext& context) :
+TaskDatabase::TaskDatabase(JobWidgetInstall * const &jobContext) :
     DPL::TaskDecl<TaskDatabase>(this),
-    m_context(context)
+    m_jobContext(jobContext)
 {
     AddStep(&TaskDatabase::StartStep);
     AddStep(&TaskDatabase::StepRegisterExternalFiles);
     AddStep(&TaskDatabase::StepWrtDBInsert);
-    AddStep(&TaskDatabase::StepAceDBInsert);
     AddStep(&TaskDatabase::StepSecurityOriginDBInsert);
     AddStep(&TaskDatabase::StepWidgetInterfaceDBInsert);
     AddStep(&TaskDatabase::StepRemoveExternalFiles);
-#ifdef DBOX_ENABLED
+#if USE(WEB_PROVIDER)
     AddStep(&TaskDatabase::StepLiveboxDBInsert);
 #endif
     AddStep(&TaskDatabase::EndStep);
 
     AddAbortStep(&TaskDatabase::StepAbortDBInsert);
-    AddAbortStep(&TaskDatabase::StepAbortAceDBInsert);
     AddAbortStep(&TaskDatabase::StepAbortWidgetInterfaceDBInsert);
 }
 
+namespace {
+const char *KEY_WIDGET_ARG = "widget_arg";
+const char* const DATABASE_JOURNAL_FILENAME = "-journal";
+
+const int APP_UID = 5000;
+const int APP_GUID = 5000;
+} // anonymous namespace
+
 void TaskDatabase::StepWrtDBInsert()
 {
     Try
     {
         /* Set install Time */
-        time(&m_context.widgetConfig.installedTime);
+        time(&m_jobContext->m_installerContext.widgetConfig.installedTime);
 
-        if (m_context.isUpdateMode) { //update
+        if (m_jobContext->m_installerContext.isUpdateMode) { //update
             _D("Registering widget... (update)");
             Try
             {
-                std::list<TizenAppId> idList = WidgetDAOReadOnly::getTzAppIdList(m_context.widgetConfig.tzPkgid);
-                FOREACH(it , idList ){
+                std::list<TizenAppId> idList = WidgetDAOReadOnly::getTzAppIdList(m_jobContext->m_installerContext.widgetConfig.tzPkgid);
+                FOREACH(it , idList{
                     //installed AppId list, It need to delete ACE Database corresponding record
                     m_handleToRemoveList.push_back(WidgetDAOReadOnly::getHandle(*it));
                     WrtDB::TizenAppId backAppId = *it + L".backup";
                     m_backAppIdList.push_back(backAppId);
                     //Change all installed tzAppid to .backup
                     WidgetDAO::updateTizenAppId(*it, backAppId);
-            }
-
-            WidgetDAO::registerWidget(m_context.widgetConfig.tzAppid,
-                                      m_context.widgetConfig,
-                                      m_context.widgetSecurity);
-                m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid));
+                }
 
-                FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) {
+                WidgetDAO::registerWidget(m_jobContext->m_installerContext.widgetConfig.tzAppid,
+                                          m_jobContext->m_installerContext.widgetConfig,
+                                          m_jobContext->m_installerContext.widgetSecurity);
+                m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_jobContext->m_installerContext.widgetConfig.tzAppid));
+    
+                FOREACH(iterator, m_jobContext->m_installerContext.widgetConfig.configInfo.serviceAppInfoList) {
                     WrtDB::TizenAppId tizenAppId = iterator->serviceId;
-                    WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity);
+                    WidgetDAO::registerService(*iterator, m_jobContext->m_installerContext.widgetConfig, m_jobContext->m_installerContext.widgetSecurity);
                     m_handleList.push_back(WidgetDAOReadOnly::getHandle(tizenAppId));
                 }
             }
             Catch(WidgetDAOReadOnly::Exception::WidgetNotExist)
             {
-                LogError(
-                    "Given tizenId not found for update installation (Same GUID?)");
+                _E("Given tizenId not found for update installation (Same GUID?)");
                 ThrowMsg(Exceptions::DatabaseFailure,
                          "Given tizenId not found for update installation");
             }
         } else { //new installation
             _D("Registering widget...");
             WidgetDAO::registerWidget(
-                m_context.widgetConfig.tzAppid,
-                m_context.widgetConfig,
-                m_context.widgetSecurity);
+                m_jobContext->m_installerContext.widgetConfig.tzAppid,
+                m_jobContext->m_installerContext.widgetConfig,
+                m_jobContext->m_installerContext.widgetSecurity);
 
-            m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid));
+            m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_jobContext->m_installerContext.widgetConfig.tzAppid));
 
-            FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) {
-                    WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity);
+            FOREACH(iterator, m_jobContext->m_installerContext.widgetConfig.configInfo.serviceAppInfoList) {
+                    WidgetDAO::registerService(*iterator, m_jobContext->m_installerContext.widgetConfig, m_jobContext->m_installerContext.widgetSecurity);
                     m_handleList.push_back(WidgetDAOReadOnly::getHandle(iterator->serviceId));
             }
         }
 
-        FOREACH(cap, m_context.staticPermittedDevCaps) {
-            _D("staticPermittedDevCaps : %ls smack status: %d", cap->first.c_str(), cap->second);
-        }
-
         _D("Widget registered");
     }
     Catch(WidgetDAO::Exception::DatabaseError)
@@ -146,33 +150,6 @@ void TaskDatabase::StepWrtDBInsert()
     }
 }
 
-void TaskDatabase::StepAceDBInsert()
-{
-    FOREACH(iterHandleToRemove, m_handleToRemoveList)
-    {
-        if (INVALID_WIDGET_HANDLE != *iterHandleToRemove) {
-            _D("Removing old insallation. Handle: %d", *iterHandleToRemove);
-            if (ACE_OK != ace_unregister_widget(
-                    static_cast<ace_widget_handle_t>(*iterHandleToRemove)))
-            {
-                _W("Error while removing ace entry for previous insallation");
-            }
-        }
-    }
-
-    FOREACH(iterHandle, m_handleList)
-    {
-        if (!AceApi::registerAceWidget(*iterHandle, m_context.widgetConfig,
-                                   m_context.widgetSecurity.getCertificateList()))
-        {
-            _E("ace database insert failed");
-            ThrowMsg(Exceptions::UpdateFailed,
-                 "Update failure. ace_register_widget failed");
-        }
-        _D("Ace data inserted");
-    }
-}
-
 void TaskDatabase::StepSecurityOriginDBInsert()
 {
     _D("Create Security origin database");
@@ -180,28 +157,80 @@ void TaskDatabase::StepSecurityOriginDBInsert()
     using namespace SecurityOriginDB;
     using namespace WrtDB;
 
-    try{
-        SecurityOriginDAO dao(m_context.locations->getPkgId());
+    try {
+        SecurityOriginDAO dao(m_jobContext->m_installerContext.locations->getPkgId());
+#ifdef DEVICE_PROFILE_MOBILE
+        DPL::OptionalString minVersion = m_jobContext->m_installerContext.widgetConfig.minVersion;
+        std::string version;
+        if (!minVersion || minVersion->empty()) {
+            ThrowMsg(Exceptions::UpdateFailed, "required_version is mandatory");
+        } else {
+            version = DPL::ToUTF8String(*minVersion);
+        }
+        double requiredVersion = atof(version.c_str());
+#endif
         // Checking privilege list for setting security origin exception data
-        FOREACH(it, m_context.widgetConfig.configInfo.privilegeList) {
+        FOREACH(it, m_jobContext->m_installerContext.widgetConfig.configInfo.privilegeList) {
             std::map<std::string, Feature>::const_iterator result =
                 g_W3CPrivilegeTextMap.find(DPL::ToUTF8String(it->name));
             if (result != g_W3CPrivilegeTextMap.end()) {
-                if (result->second == FEATURE_USER_MEDIA) {
+#ifdef DEVICE_PROFILE_MOBILE
+                if (result->second == FEATURE_USER_MEDIA && requiredVersion < 2.3) {
                     dao.setPrivilegeSecurityOriginData(result->second, false);
                 } else if (result->second == FEATURE_FULLSCREEN_MODE) {
                     continue;
                 } else {
                     dao.setPrivilegeSecurityOriginData(result->second);
                 }
+#endif
+#ifdef DEVICE_PROFILE_WEARABLE
+                if (result->second == FEATURE_FULLSCREEN_MODE) {
+                    continue;
+                }
+#endif
             }
         }
-    }catch(const SecurityOriginDAO::Exception::DatabaseError& err){
+    } catch(const SecurityOriginDAO::Exception::DatabaseError& err){
         _E("error open SecurityOrigin db %s", err.GetMessage().c_str());
         ThrowMsg(Exceptions::UpdateFailed, "Cannot open SecurityOrigin DB");
     }
 }
 
+static bool closeDatabase(sqlite3* dbHandle)
+{
+    if (DB_UTIL_OK != db_util_close(dbHandle)) {
+        _E("Failed to close widget interface database");
+        return false;
+    }
+    return true;
+}
+static void copyPropertiesFromWrtDatabase(DbWidgetHandle handle)
+{
+    WrtDB::WrtDatabase::attachToThreadRO();
+    WidgetInterfaceDB::WidgetInterfaceDAO dao(handle);
+    Try{
+        WrtDB::PropertyDAOReadOnly::WidgetPreferenceList existing =
+            WrtDB::PropertyDAOReadOnly::GetPropertyList(
+                    WrtDB::WidgetDAOReadOnly::getTizenAppId(handle)
+        );
+
+        for (auto prop: existing) {
+            std::string key = DPL::ToUTF8String(prop.key_name);
+            if (key != KEY_WIDGET_ARG) {
+                std::string value;
+                if (!!prop.key_value) {
+                    value = DPL::ToUTF8String(*(prop.key_value));
+                }
+                bool readonly = !!prop.readonly && (*prop.readonly);
+                dao.setItem(key, value, readonly, true);
+            }
+        }
+    } Catch(WrtDB::WidgetDAOReadOnly::Exception::DatabaseError) {
+        ReThrowMsg(WidgetInterfaceDB::WidgetInterfaceDAO::Exception::DatabaseError, "Cannot copy properties read from config.xml");
+    }
+    WrtDB::WrtDatabase::detachFromThread();
+}
+
 void TaskDatabase::StepWidgetInterfaceDBInsert()
 {
     _D("Create Widget Interface database");
@@ -209,11 +238,12 @@ void TaskDatabase::StepWidgetInterfaceDBInsert()
     using namespace WrtDB;
 
     DbWidgetHandle handle =
-        WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid);
+        WidgetDAOReadOnly::getHandle(m_jobContext->m_installerContext.widgetConfig.tzAppid);
+
+    std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle);
 
     // backup database
-    if (m_context.isUpdateMode) {
-        std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle);
+    if (m_jobContext->m_installerContext.isUpdateMode) {
         std::string backupDbPath = dbPath;
         backupDbPath += GlobalConfig::GetBackupDatabaseSuffix();
         _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str());
@@ -226,8 +256,42 @@ void TaskDatabase::StepWidgetInterfaceDBInsert()
 
     Try
     {
-        // automatically create widget interface database
-        WidgetInterfaceDAO dao(handle);
+        // Create widget interface database
+        _D("Creating database. %s", dbPath.c_str());
+        sqlite3 *dbHandle;
+        // Open & Exec query
+        if (DB_UTIL_OK != db_util_open_with_options(dbPath.c_str(), &dbHandle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
+            ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "widget interface database create failed");
+        }
+
+        char* error = NULL;
+        int ret = sqlite3_exec(dbHandle,
+                               "create table Properties(key TEXT NOT NULL, value TEXT DEFAULT '' NOT NULL, readonly INTEGER check(readonly between 0 and 1) DEFAULT 0, configxml INTEGER check(readonly between 0 and 1) DEFAULT 0, UNIQUE (key))",
+                               NULL,
+                               NULL,
+                               &error);
+        if (SQLITE_OK != ret) {
+            _E("Cannot exec query. %s", error);
+            closeDatabase(dbHandle);
+            ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "Cannot execute query");
+        }
+
+        if (!closeDatabase(dbHandle)){
+            _E("widget interface database create failed");
+            ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "Cannot close db");
+        }
+
+        // Copy widget interface data from .wrt.db
+        copyPropertiesFromWrtDatabase(handle);
+
+        // Change owner & permission
+        if(chown(dbPath.c_str(), APP_UID, APP_GUID) != 0) {
+            ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "Fail to change uid/guid");
+        }
+        std::string databaseJournal = dbPath + DATABASE_JOURNAL_FILENAME;
+        if(chown(databaseJournal.c_str(), APP_UID, APP_GUID) != 0) {
+            ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "Fail to change uid/guid");
+        }
     }
     Catch(WidgetInterfaceDAO::Exception::DatabaseError)
     {
@@ -240,11 +304,11 @@ void TaskDatabase::StepWidgetInterfaceDBInsert()
 void TaskDatabase::StepRegisterExternalFiles()
 {
     WrtDB::ExternalLocationList externalLocationsUpdate =
-        m_context.locations->listExternalLocations();
-    if (m_context.isUpdateMode) { //update
+        m_jobContext->m_installerContext.locations->listExternalLocations();
+    if (m_jobContext->m_installerContext.isUpdateMode) { //update
         Try
         {
-            WidgetDAOReadOnly dao(WidgetDAOReadOnly::getHandleByPkgId(m_context.widgetConfig.tzPkgid));
+            WidgetDAOReadOnly dao(WidgetDAOReadOnly::getHandleByPkgId(m_jobContext->m_installerContext.widgetConfig.tzPkgid));
             WrtDB::ExternalLocationList externalLocationsDB =
                 dao.getWidgetExternalLocations();
             FOREACH(file, externalLocationsDB)
@@ -271,7 +335,7 @@ void TaskDatabase::StepRegisterExternalFiles()
     }
 
     //set external locations to be registered
-    m_context.widgetConfig.externalLocations = externalLocationsUpdate;
+    m_jobContext->m_installerContext.widgetConfig.externalLocations = externalLocationsUpdate;
 }
 
 void TaskDatabase::StepRemoveExternalFiles()
@@ -282,20 +346,22 @@ void TaskDatabase::StepRemoveExternalFiles()
 
     FOREACH(file, m_externalLocationsToRemove)
     {
-        if (WrtUtilFileExists(*file)) {
-            _D("  -> %s", (*file).c_str());
-            if (-1 == remove(file->c_str())) {
-                ThrowMsg(Exceptions::RemovingFileFailure,
-                         "Failed to remove external file");
-            }
-        } else if (WrtUtilDirExists(*file)) {
-            _D("  -> %s", (*file).c_str());
-            if (!WrtUtilRemove(*file)) {
-                ThrowMsg(Exceptions::RemovingFolderFailure,
-                         "Failed to remove external directory");
+        bf::path p(*file);
+        try {
+            if (bf::is_regular_file(p)) {
+                _D("  -> %s", (*file).c_str());
+                if (-1 == TEMP_FAILURE_RETRY(remove(file->c_str()))) {
+                    ThrowMsg(Exceptions::RemovingFileFailure,
+                             "Failed to remove external file");
+                }
+            } else if (bf::is_directory(p)) {
+                _D("  -> %s", (*file).c_str());
+                JobWidgetInstall::SecureRemove(p);
+            } else {
+                _W("  -> %s(no such a path)", (*file).c_str());
             }
-        } else {
-            _W("  -> %s(no such a path)", (*file).c_str());
+        } catch (const bf::filesystem_error& ex) {
+            _E("bf::filesystem::error: %s",ex.what());
         }
     }
 }
@@ -305,17 +371,17 @@ void TaskDatabase::StepAbortDBInsert()
     _W("[DB Update Task] Aborting... (DB Clean)");
     Try
     {
-            WidgetDAO::unregisterWidget(m_context.widgetConfig.tzAppid);
+        WidgetDAO::unregisterWidget(m_jobContext->m_installerContext.widgetConfig.tzAppid);
 
-        FOREACH(iter, m_context.widgetConfig.configInfo.serviceAppInfoList) {
+        FOREACH(iter, m_jobContext->m_installerContext.widgetConfig.configInfo.serviceAppInfoList) {
             WidgetDAO::unregisterWidget(iter->serviceId);
         }
 
-        if (m_context.isUpdateMode) {
+        if (m_jobContext->m_installerContext.isUpdateMode) {
             FOREACH(iter, m_backAppIdList) {
                 unsigned pos = (*iter).find(L".backup");
-                TizenAppId str = (*iter).substr(0, pos);
-                WidgetDAO::updateTizenAppId(*iter, str);
+                TizenAppId str = (*iter).substr(0,pos);
+                WidgetDAO::updateTizenAppId(*iter,str);
             }
         }
         _D("Cleaning DB successful!");
@@ -326,29 +392,6 @@ void TaskDatabase::StepAbortDBInsert()
     }
 }
 
-void TaskDatabase::StepAbortAceDBInsert()
-{
-    _W("[DB Update Task] ACE DB Aborting... (DB Clean)");
-
-    FOREACH(iter, m_handleList) {
-            ace_unregister_widget(static_cast<ace_widget_handle_t>(*iter));
-    }
-
-    FOREACH(iter, m_handleToRemoveList) {
-        // Remove also old one. If it was already updated nothing wrong will happen,
-        // but if not old widget will be removed.
-        if (INVALID_WIDGET_HANDLE != *iter) {
-            ace_unregister_widget(static_cast<ace_widget_handle_t>(*iter));
-        }
-
-        if (!AceApi::registerAceWidgetFromDB(*iter))
-        {
-        _E("ace database restore failed");
-        }
-    }
-    _D("Ace data inserted");
-}
-
 void TaskDatabase::StepAbortWidgetInterfaceDBInsert()
 {
     _D("[DB Update Task] Widget interface Aborting...");
@@ -356,7 +399,7 @@ void TaskDatabase::StepAbortWidgetInterfaceDBInsert()
     using namespace WrtDB;
 
     DbWidgetHandle handle =
-        WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid);
+        WidgetDAOReadOnly::getHandle(m_jobContext->m_installerContext.widgetConfig.tzAppid);
     std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle);
 
     // remove database
@@ -365,7 +408,7 @@ void TaskDatabase::StepAbortWidgetInterfaceDBInsert()
     }
 
     // rollback database
-    if (m_context.isUpdateMode) {
+    if (m_jobContext->m_installerContext.isUpdateMode) {
         std::string backupDbPath = dbPath;
         backupDbPath += GlobalConfig::GetBackupDatabaseSuffix();
         _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str());
@@ -375,23 +418,23 @@ void TaskDatabase::StepAbortWidgetInterfaceDBInsert()
     }
 }
 
-#ifdef DBOX_ENABLED
+#if USE(WEB_PROVIDER)
 void TaskDatabase::StepLiveboxDBInsert()
 {
-    if (m_context.widgetConfig.configInfo.m_livebox.size() <= 0) {
+    if (m_jobContext->m_installerContext.widgetConfig.configInfo.m_livebox.size() <= 0) {
         return;
     }
 
-    std::string tizenId = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
+    std::string tizenId = DPL::ToUTF8String(m_jobContext->m_installerContext.widgetConfig.tzAppid);
 
     // insert specific information to web livebox db
-    for (auto it = m_context.widgetConfig.configInfo.m_livebox.begin();
-         it != m_context.widgetConfig.configInfo.m_livebox.end(); ++it)
+    for (auto it = m_jobContext->m_installerContext.widgetConfig.configInfo.m_livebox.begin();
+         it != m_jobContext->m_installerContext.widgetConfig.configInfo.m_livebox.end(); ++it)
     {
         std::string boxId = DPL::ToUTF8String((**it).m_liveboxId);
         std::string boxType;
         if ((**it).m_type.empty()) {
-            boxType = web_provider_livebox_get_default_type();
+            boxType = web_provider_widget_get_default_type();
         } else {
             boxType = DPL::ToUTF8String((**it).m_type);
         }
@@ -407,10 +450,10 @@ void TaskDatabase::StepLiveboxDBInsert()
         int pdFastOpen = (**it).m_boxInfo.m_pdFastOpen == L"true" ? 1 : 0;
         _D("livebox pd fast-open: %d", pdFastOpen);
 
-        if (m_context.isUpdateMode) {
-            web_provider_livebox_delete_by_app_id(tizenId.c_str());
+        if (m_jobContext->m_installerContext.isUpdateMode) {
+            web_provider_widget_delete_by_app_id(tizenId.c_str());
         }
-        web_provider_livebox_insert_box_info(
+        web_provider_widget_insert_box_info(
                 boxId.c_str(), tizenId.c_str(), boxType.c_str(),
                 autoLaunch, mouseEvent, pdFastOpen);
     }
@@ -419,12 +462,12 @@ void TaskDatabase::StepLiveboxDBInsert()
 
 void TaskDatabase::StartStep()
 {
-    LOGD("--------- <TaskDatabase> : START ----------");
+    LOGI("--------- <TaskDatabase> : START ----------");
 }
 
 void TaskDatabase::EndStep()
 {
-    LOGD("--------- <TaskDatabase> : END ----------");
+    LOGI("--------- <TaskDatabase> : END ----------");
 }
 } //namespace WidgetInstall
 } //namespace Jobs