--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
+PROJECT(WgtBackend)
+SET(PREFIX "${CMAKE_INSTALL_PREFIX}")
+SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
+SET(LIBDIR "${CMAKE_INSTALL_LIBDIR}")
+SET(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share")
+SET(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
+SET(VERSION_MAJOR 0)
+SET(VERSION "${VERSION_MAJOR}.1.0")
+
+IF(NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "Release")
+ENDIF(NOT CMAKE_BUILD_TYPE)
+
+# Compiler flags
+SET(CMAKE_C_FLAGS_PROFILING "-O2")
+SET(CMAKE_CXX_FLAGS_PROFILING "-O2 -std=c++11")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -std=c++11 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -std=c++11 -g")
+SET(CMAKE_CXX_FLAGS_CCOV "-O0 -std=c++11 -g --coverage")
+
+# Targets
+SET(TARGET_LIBNAME_WGT "wgt-installer")
+SET(TARGET_WGT_BACKEND "wgt-backend")
+SET(TARGET_SMOKE_TEST "smoke_test")
+
+ADD_DEFINITIONS("-Wall")
+ADD_DEFINITIONS("-Wextra")
+ADD_DEFINITIONS("-fPIE")
+ADD_DEFINITIONS("-fPIC")
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
+INCLUDE(FindPkgConfig)
+INCLUDE(ApplyPkgConfig)
+
+# Find all needed packages once
+PKG_CHECK_MODULES(APP_INSTALLERS_DEPS REQUIRED app-installers)
+PKG_CHECK_MODULES(MANIFEST_HANDLERS_DEPS REQUIRED manifest-handlers)
+PKG_CHECK_MODULES(MANIFEST_PARSER_DEPS REQUIRED manifest-parser)
+PKG_CHECK_MODULES(PKGMGR_INSTALLER_DEPS REQUIRED pkgmgr-installer)
+PKG_CHECK_MODULES(ENCRYPTION_DEPS REQUIRED libwebappenc)
+
+FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem regex program_options)
+FIND_PACKAGE(GTest REQUIRED)
+
+ADD_SUBDIRECTORY(src)
--- /dev/null
+# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+#
+# This function applies external (out of source tree) dependencies
+# to given target. Arguments are:
+# TARGET - valid cmake target
+# PRIVACY - dependency can be inherited by dependent targets or not:
+# PUBLIC - this should be used by default, cause compile/link flags passing
+# PRIVATE - do not passes any settings to dependent targets,
+# may be usefull for static libraries from the inside of the project
+# Argument ARGV2 and following are supposed to be names of checked pkg config
+# packages. This function will use variables created by check_pkg_modules().
+# - ${DEP_NAME}_LIBRARIES
+# - ${DEP_NAME}_INCLUDE_DIRS
+# - ${DEP_NAME}_CFLAGS
+#
+FUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY)
+ MATH(EXPR DEST_INDEX "${ARGC}-1")
+ FOREACH(I RANGE 2 ${DEST_INDEX})
+ IF(NOT ${ARGV${I}}_FOUND)
+ MESSAGE(FATAL_ERROR "Not found dependency - ${ARGV${I}}_FOUND")
+ ENDIF(NOT ${ARGV${I}}_FOUND)
+ TARGET_LINK_LIBRARIES(${TARGET} ${PRIVACY} "${${ARGV${I}}_LIBRARIES}")
+ TARGET_INCLUDE_DIRECTORIES(${TARGET} ${PRIVACY} SYSTEM "${${ARGV${I}}_INCLUDE_DIRS}")
+ STRING(REPLACE ";" " " CFLAGS_STR "${${ARGV${I}}_CFLAGS}")
+ SET(CFLAGS_LIST ${CFLAGS_STR})
+ SEPARATE_ARGUMENTS(CFLAGS_LIST)
+ FOREACH(OPTION ${CFLAGS_LIST})
+ TARGET_COMPILE_OPTIONS(${TARGET} ${PRIVACY} ${OPTION})
+ ENDFOREACH(OPTION)
+ SET_TARGET_PROPERTIES(${TARGET} PROPERTIES SKIP_BUILD_RPATH true)
+ ENDFOREACH(I RANGE 2 ${DEST_INDEX})
+ENDFUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY)
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/wgt-backend-ut/smoke_test" exec_label="User" />
+ </assign>
+</manifest>
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/wgt-backend" exec_label="User" />
+ </assign>
+</manifest>
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
+Source1000: wgt-backend.manifest
+Source1001: wgt-backend-tests.manifest
+
+BuildRequires: boost-devel
+BuildRequires: cmake
+BuildRequires: gtest-devel
+BuildRequires: pkgconfig(app-installers)
+BuildRequires: pkgconfig(manifest-parser)
+BuildRequires: pkgconfig(manifest-handlers)
+BuildRequires: pkgconfig(pkgmgr-installer)
+BuildRequires: pkgconfig(libwebappenc)
+
+%description
+This is a package that installs the WGT backend of pkgmgr.
+
+%package tests
+Summary: Unit tests for wgt-backend
+Requires: %{name} = %{version}
+
+%description tests
+Unit tests for wgt-backend
+
+%prep
+%setup -q
+
+cp %{SOURCE1000} .
+cp %{SOURCE1001} .
+
+%build
+#Variable for setting symlink to runtime
+runtime_path=%{_bindir}/xwalk-launcher
+%if "%{profile}" == "mobile" || "%{profile}" == "wearable" || "%{profile}" == "tv"
+runtime_path=%{_bindir}/wrt
+%endif
+%cmake . -DCMAKE_BUILD_TYPE=%{?build_type:%build_type} -DWRT_LAUNCHER=${runtime_path}
+make %{?_smp_mflags}
+
+%install
+%make_install
+mkdir -p %{buildroot}/etc/package-manager/backend
+ln -s %{_bindir}/wgt-backend %{buildroot}%{_sysconfdir}/package-manager/backend/wgt
+
+%files
+%manifest wgt-backend.manifest
+%license LICENSE
+%{_sysconfdir}/package-manager/backend/wgt
+%{_bindir}/wgt-backend
+
+%files tests
+%manifest wgt-backend-tests.manifest
+%{_bindir}/wgt-backend-ut/*
+%{_datadir}/wgt-backend-ut/*
%changelog
* Thu Dec 18 2015 Pawel Sikorski <p.sikorski@samsung.com> 0.1-1
- initial files creation
-
-
--- /dev/null
+ADD_SUBDIRECTORY(wgt)
+ADD_SUBDIRECTORY(unit_tests)
--- /dev/null
+SET(DESTINATION_DIR wgt-backend-ut)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+# Executables
+ADD_EXECUTABLE(${TARGET_SMOKE_TEST}
+ smoke_test.cc
+)
+
+INSTALL(DIRECTORY test_samples/ DESTINATION ${SHAREDIR}/${DESTINATION_DIR}/test_samples)
+
+APPLY_PKG_CONFIG(smoke_test PUBLIC
+ Boost
+ GTEST
+)
+
+# FindGTest module do not sets all needed libraries in GTEST_LIBRARIES and
+# GTest main libraries is still missing, so additional linking of
+# GTEST_MAIN_LIBRARIES is needed.
+target_link_libraries(smoke_test PRIVATE ${TARGET_LIBNAME_WGT} ${GTEST_MAIN_LIBRARIES})
+
+INSTALL(TARGETS smoke_test DESTINATION ${BINDIR}/${DESTINATION_DIR})
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/system/error_code.hpp>
+#include <common/backup_paths.h>
+#include <common/pkgmgr_interface.h>
+#include <common/pkgmgr_registration.h>
+#include <common/request.h>
+#include <common/step/step_fail.h>
+#include <gtest/gtest.h>
+#include <gtest/gtest-death-test.h>
+#include <pkgmgr-info.h>
+#include <signal.h>
+#include <unistd.h>
+#include <tzplatform_config.h>
+
+#include <array>
+#include <cstdio>
+#include <cstdlib>
+
+#include "wgt/wgt_app_query_interface.h"
+#include "wgt/wgt_installer.h"
+
+#define SIZEOFARRAY(ARR) \
+ sizeof(ARR) / sizeof(ARR[0]) \
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+
+namespace {
+
+const char kApplicationDir[] = ".applications";
+const char kApplicationDirBackup[] = ".applications.bck";
+const char KUserAppsDir[] = "apps_rw";
+const char KUserAppsDirBackup[] = "apps_rw.bck";
+
+enum class RequestResult {
+ NORMAL,
+ FAIL,
+ CRASH
+};
+
+class StepCrash : public ci::Step {
+ public:
+ using Step::Step;
+
+ ci::Step::Status process() override {
+ raise(SIGSEGV);
+ return Status::OK;
+ }
+ ci::Step::Status clean() override { return ci::Step::Status::OK; }
+ ci::Step::Status undo() override { return ci::Step::Status::OK; }
+ ci::Step::Status precheck() override { return ci::Step::Status::OK; }
+};
+
+void RemoveAllRecoveryFiles() {
+ bf::path root_path = ci::GetRootAppPath();
+ for (auto& dir_entry : boost::make_iterator_range(
+ bf::directory_iterator(root_path), bf::directory_iterator())) {
+ if (bf::is_regular_file(dir_entry)) {
+ if (dir_entry.path().string().find("/recovery") != std::string::npos) {
+ bs::error_code error;
+ bf::remove(dir_entry.path(), error);
+ }
+ }
+ }
+}
+
+bf::path FindRecoveryFile() {
+ bf::path root_path = ci::GetRootAppPath();
+ for (auto& dir_entry : boost::make_iterator_range(
+ bf::directory_iterator(root_path), bf::directory_iterator())) {
+ if (bf::is_regular_file(dir_entry)) {
+ if (dir_entry.path().string().find("/recovery") != std::string::npos) {
+ return dir_entry.path();
+ }
+ }
+ }
+ return {};
+}
+
+bool ValidateFileContentInPackage(const std::string& pkgid,
+ const std::string& relative,
+ const std::string& expected) {
+ bf::path root_path = ci::GetRootAppPath();
+ bf::path file_path = root_path / pkgid / relative;
+ if (!bf::exists(file_path)) {
+ LOG(ERROR) << file_path << " doesn't exist";
+ return false;
+ }
+ FILE* handle = fopen(file_path.c_str(), "r");
+ if (!handle) {
+ LOG(ERROR) << file_path << " cannot be open";
+ return false;
+ }
+ std::string content;
+ std::array<char, 200> buffer;
+ while (fgets(buffer.data(), buffer.size(), handle)) {
+ content += buffer.data();
+ }
+ fclose(handle);
+ return content == expected;
+}
+
+void ValidatePackageFS(const std::string& pkgid, const std::string& appid) {
+ bf::path root_path = ci::GetRootAppPath();
+ bf::path package_path = root_path / pkgid;
+ bf::path binary_path = package_path / "bin" / appid;
+ bf::path data_path = package_path / "data";
+ bf::path shared_path = package_path / "shared";
+ bf::path cache_path = package_path / "cache";
+ ASSERT_TRUE(bf::exists(root_path));
+ ASSERT_TRUE(bf::exists(package_path));
+ ASSERT_TRUE(bf::exists(binary_path));
+ ASSERT_TRUE(bf::exists(data_path));
+ ASSERT_TRUE(bf::exists(shared_path));
+ ASSERT_TRUE(bf::exists(cache_path));
+
+ bf::path manifest_path =
+ bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
+ bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
+ ASSERT_TRUE(bf::exists(manifest_path));
+ ASSERT_TRUE(bf::exists(icon_path));
+
+ bf::path widget_root_path = package_path / "res" / "wgt";
+ bf::path config_path = widget_root_path / "config.xml";
+ ASSERT_TRUE(bf::exists(widget_root_path));
+ ASSERT_TRUE(bf::exists(config_path));
+
+ bf::path private_tmp_path = package_path / "tmp";
+ ASSERT_TRUE(bf::exists(private_tmp_path));
+
+ // backups should not exist
+ bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
+ bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
+ bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
+ ASSERT_FALSE(bf::exists(package_backup));
+ ASSERT_FALSE(bf::exists(manifest_backup));
+ ASSERT_FALSE(bf::exists(icon_backup));
+}
+
+void PackageCheckCleanup(const std::string& pkgid, const std::string& appid) {
+ bf::path root_path = ci::GetRootAppPath();
+ bf::path package_path = root_path / pkgid;
+ ASSERT_FALSE(bf::exists(package_path));
+
+ bf::path manifest_path =
+ bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
+ bf::path icon_path = bf::path(getIconPath(getuid())) / (appid + ".png");
+ ASSERT_FALSE(bf::exists(manifest_path));
+ ASSERT_FALSE(bf::exists(icon_path));
+
+ // backups should not exist
+ bf::path package_backup = ci::GetBackupPathForPackagePath(package_path);
+ bf::path manifest_backup = ci::GetBackupPathForManifestFile(manifest_path);
+ bf::path icon_backup = ci::GetBackupPathForIconFile(icon_path);
+ ASSERT_FALSE(bf::exists(package_backup));
+ ASSERT_FALSE(bf::exists(manifest_backup));
+ ASSERT_FALSE(bf::exists(icon_backup));
+}
+
+void ValidatePackage(const std::string& pkgid, const std::string& appid) {
+ ASSERT_TRUE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
+ ValidatePackageFS(pkgid, appid);
+}
+
+void CheckPackageNonExistance(const std::string& pkgid,
+ const std::string& appid) {
+ ASSERT_FALSE(ci::IsPackageInstalled(pkgid, ci::GetRequestMode()));
+ PackageCheckCleanup(pkgid, appid);
+}
+
+std::unique_ptr<ci::AppQueryInterface> CreateQueryInterface() {
+ std::unique_ptr<ci::AppQueryInterface> query_interface(
+ new wgt::WgtAppQueryInterface());
+ return query_interface;
+}
+
+std::unique_ptr<ci::AppInstaller> CreateInstaller(ci::PkgMgrPtr pkgmgr) {
+ std::unique_ptr<ci::AppInstaller> installer(new wgt::WgtInstaller(pkgmgr));
+ return installer;
+}
+
+ci::AppInstaller::Result RunInstallerWithPkgrmgr(ci::PkgMgrPtr pkgmgr,
+ RequestResult mode) {
+ std::unique_ptr<ci::AppInstaller> installer = CreateInstaller(pkgmgr);
+ switch (mode) {
+ case RequestResult::FAIL:
+ installer->AddStep<ci::configuration::StepFail>();
+ break;
+ case RequestResult::CRASH:
+ installer->AddStep<StepCrash>();
+ default:
+ break;
+ }
+ return installer->Run();
+}
+
+ci::AppInstaller::Result Install(const bf::path& path,
+ RequestResult mode = RequestResult::NORMAL) {
+ const char* argv[] = {"", "-i", path.c_str()};
+ std::unique_ptr<ci::AppQueryInterface> query_interface =
+ CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return RunInstallerWithPkgrmgr(pkgmgr, mode);
+}
+
+ci::AppInstaller::Result Update(const bf::path& path_old,
+ const bf::path& path_new,
+ RequestResult mode = RequestResult::NORMAL) {
+ if (Install(path_old) != ci::AppInstaller::Result::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot update";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return Install(path_new, mode);
+}
+
+ci::AppInstaller::Result Uninstall(const std::string& pkgid,
+ RequestResult mode = RequestResult::NORMAL) {
+ const char* argv[] = {"", "-d", pkgid.c_str()};
+ std::unique_ptr<ci::AppQueryInterface> query_interface =
+ CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return RunInstallerWithPkgrmgr(pkgmgr, mode);
+}
+
+ci::AppInstaller::Result Reinstall(const bf::path& path,
+ const bf::path& delta_dir,
+ RequestResult mode = RequestResult::NORMAL) {
+ if (Install(path) != ci::AppInstaller::Result::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot perform RDS";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ const char* argv[] = {"", "-r", delta_dir.c_str()};
+ std::unique_ptr<ci::AppQueryInterface> query_interface =
+ CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return RunInstallerWithPkgrmgr(pkgmgr, mode);
+}
+
+ci::AppInstaller::Result DeltaInstall(const bf::path& path,
+ const bf::path& delta_package) {
+ if (Install(path) != ci::AppInstaller::Result::OK) {
+ LOG(ERROR) << "Failed to install application. Cannot perform RDS";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return Install(delta_package);
+}
+
+ci::AppInstaller::Result Recover(const bf::path& recovery_file,
+ RequestResult mode = RequestResult::NORMAL) {
+ const char* argv[] = {"", "-e", recovery_file.c_str()};
+ std::unique_ptr<ci::AppQueryInterface> query_interface =
+ CreateQueryInterface();
+ auto pkgmgr =
+ ci::PkgMgrInterface::Create(SIZEOFARRAY(argv), const_cast<char**>(argv),
+ query_interface.get());
+ if (!pkgmgr) {
+ LOG(ERROR) << "Failed to initialize pkgmgr interface";
+ return ci::AppInstaller::Result::UNKNOWN;
+ }
+ return RunInstallerWithPkgrmgr(pkgmgr, mode);
+}
+
+} // namespace
+
+namespace common_installer {
+
+class SmokeEnvironment : public testing::Environment {
+ public:
+ explicit SmokeEnvironment(const bf::path& home) : home_(home) {
+ }
+ void SetUp() override {
+ bs::error_code error;
+ bf::remove_all(home_ / kApplicationDirBackup, error);
+ bf::remove_all(home_ / KUserAppsDirBackup, error);
+ if (bf::exists(home_ / KUserAppsDir)) {
+ bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error);
+ assert(!error);
+ }
+ if (bf::exists(home_ / kApplicationDir)) {
+ bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error);
+ assert(!error);
+ }
+ }
+ void TearDown() override {
+ bs::error_code error;
+ bf::remove_all(home_ / kApplicationDir, error);
+ bf::remove_all(home_ / KUserAppsDir, error);
+ if (bf::exists(home_ / KUserAppsDirBackup))
+ bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error);
+ if (bf::exists(home_ / kApplicationDirBackup))
+ bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error);
+ }
+
+ private:
+ bf::path home_;
+};
+
+class SmokeTest : public testing::Test {
+};
+
+TEST_F(SmokeTest, InstallationMode) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/InstallationMode.wgt"; // NOLINT
+ std::string pkgid = "smokeapp03";
+ std::string appid = "smokeapp03.InstallationMode";
+ ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK);
+ ValidatePackage(pkgid, appid);
+}
+
+TEST_F(SmokeTest, UpdateMode) {
+ bf::path path_old = "/usr/share/app-installers-ut/test_samples/smoke/UpdateMode.wgt"; // NOLINT
+ bf::path path_new = "/usr/share/app-installers-ut/test_samples/smoke/UpdateMode_2.wgt"; // NOLINT
+ std::string pkgid = "smokeapp04";
+ std::string appid = "smokeapp04.UpdateMode";
+ ASSERT_EQ(Update(path_old, path_new), ci::AppInstaller::Result::OK);
+ ValidatePackage(pkgid, appid);
+
+ ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "2\n"));
+}
+
+TEST_F(SmokeTest, DeinstallationMode) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/DeinstallationMode.wgt"; // NOLINT
+ std::string pkgid = "smokeapp05";
+ std::string appid = "smokeapp05.DeinstallationMode";
+ ASSERT_EQ(Install(path),
+ ci::AppInstaller::Result::OK);
+ ASSERT_EQ(Uninstall(pkgid), ci::AppInstaller::Result::OK);
+ CheckPackageNonExistance(pkgid, appid);
+}
+
+TEST_F(SmokeTest, RDSMode) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/RDSMode.wgt"; // NOLINT
+ std::string delta_directory = "/usr/share/app-installers-ut/test_samples/smoke/delta_dir/"; // NOLINT
+ std::string pkgid = "smokeapp11";
+ std::string appid = "smokeapp11.RDSMode";
+ ASSERT_EQ(Reinstall(path, delta_directory),
+ ci::AppInstaller::Result::OK);
+ ValidatePackage(pkgid, appid);
+
+ // Check delta modifications
+ bf::path root_path = ci::GetRootAppPath();
+ ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
+ ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
+ ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "2\n");
+}
+
+TEST_F(SmokeTest, DeltaMode) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/DeltaMode.wgt"; // NOLINT
+ std::string delta_package = "/usr/share/app-installers-ut/test_samples/smoke/DeltaMode.delta"; // NOLINT
+ std::string pkgid = "smokeapp17";
+ std::string appid = "smokeapp17.DeltaMode";
+ ASSERT_EQ(DeltaInstall(path, delta_package),
+ ci::AppInstaller::Result::OK);
+ ValidatePackage(pkgid, appid);
+
+ // Check delta modifications
+ bf::path root_path = ci::GetRootAppPath();
+ ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "DELETED"));
+ ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "ADDED"));
+ ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "css" / "style.css")); // NOLINT
+ ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "images" / "tizen_32.png")); // NOLINT
+ ASSERT_TRUE(bf::exists(root_path / pkgid / "res" / "wgt" / "js" / "main.js"));
+ ValidateFileContentInPackage(pkgid, "res/wgt/MODIFIED", "version 2\n");
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForInstallation) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/RecoveryMode_ForInstallation.wgt"; // NOLINT
+ ASSERT_DEATH(Install(path, RequestResult::CRASH), ".*");
+
+ std::string pkgid = "smokeapp09";
+ std::string appid = "smokeapp09.RecoveryModeForInstallation";
+ bf::path recovery_file = FindRecoveryFile();
+ ASSERT_FALSE(recovery_file.empty());
+ ASSERT_EQ(Recover(recovery_file),
+ ci::AppInstaller::Result::OK);
+ CheckPackageNonExistance(pkgid, appid);
+}
+
+TEST_F(SmokeTest, RecoveryMode_ForUpdate) {
+ bf::path path_old = "/usr/share/app-installers-ut/test_samples/smoke/RecoveryMode_ForUpdate.wgt"; // NOLINT
+ bf::path path_new = "/usr/share/app-installers-ut/test_samples/smoke/RecoveryMode_ForUpdate_2.wgt"; // NOLINT
+ RemoveAllRecoveryFiles();
+ ASSERT_DEATH(Update(path_old, path_new, RequestResult::CRASH), ".*");
+
+ std::string pkgid = "smokeapp10";
+ std::string appid = "smokeapp10.RecoveryModeForUpdate";
+ bf::path recovery_file = FindRecoveryFile();
+ ASSERT_FALSE(recovery_file.empty());
+ ASSERT_EQ(Recover(recovery_file),
+ ci::AppInstaller::Result::OK);
+ ValidatePackage(pkgid, appid);
+
+ ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+}
+
+TEST_F(SmokeTest, InstallationMode_GoodSignature) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/InstallationMode_GoodSignature.wgt"; // NOLINT
+ ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK);
+}
+
+TEST_F(SmokeTest, InstallationMode_WrongSignature) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/InstallationMode_WrongSignature.wgt"; // NOLINT
+ ASSERT_EQ(Install(path), ci::AppInstaller::Result::ERROR);
+}
+
+TEST_F(SmokeTest, InstallationMode_Rollback) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/InstallationMode_Rollback.wgt"; // NOLINT
+ std::string pkgid = "smokeapp06";
+ std::string appid = "smokeapp06.InstallationModeRollback";
+ ASSERT_EQ(Install(path, RequestResult::FAIL),
+ ci::AppInstaller::Result::ERROR);
+ CheckPackageNonExistance(pkgid, appid);
+}
+
+TEST_F(SmokeTest, UpdateMode_Rollback) {
+ bf::path path_old = "/usr/share/app-installers-ut/test_samples/smoke/UpdateMode_Rollback.wgt"; // NOLINT
+ bf::path path_new = "/usr/share/app-installers-ut/test_samples/smoke/UpdateMode_Rollback_2.wgt"; // NOLINT
+ std::string pkgid = "smokeapp07";
+ std::string appid = "smokeapp07.UpdateModeRollback";
+ ASSERT_EQ(Update(path_old, path_new, RequestResult::FAIL),
+ ci::AppInstaller::Result::ERROR);
+ ValidatePackage(pkgid, appid);
+
+ ASSERT_TRUE(ValidateFileContentInPackage(pkgid, "res/wgt/VERSION", "1\n"));
+}
+
+TEST_F(SmokeTest, DeinstallationMode_Rollback) {
+ bf::path path = "/usr/share/app-installers-ut/test_samples/smoke/DeinstallationMode_Rollback.wgt"; // NOLINT
+ std::string pkgid = "smokeapp08";
+ std::string appid = "smokeapp08.DeinstallationModeRollback";
+ ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK);
+ ASSERT_EQ(Uninstall(pkgid, RequestResult::FAIL),
+ ci::AppInstaller::Result::ERROR);
+ ValidatePackage(pkgid, appid);
+}
+
+} // namespace common_installer
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ const char* directory = getenv("HOME");
+ if (!directory) {
+ LOG(ERROR) << "Cannot get $HOME value";
+ return 1;
+ }
+ testing::AddGlobalTestEnvironment(
+ new common_installer::SmokeEnvironment(directory));
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+#add
+ADDED
+#modify
+MODIFIED
+#delete
+DELETED
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns:tizen="http://tizen.org/ns/widgets" xmlns="http://www.w3.org/ns/widgets" id="http://yourdomain/smokeapp1" version="1.0.0" viewmodes="maximized">
+ <tizen:application id="smokeapp11.RDSMode" package="smokeapp11" required_version="2.3"/>
+ <content src="index.html"/>
+ <feature name="http://tizen.org/feature/screen.size.all"/>
+ <icon src="icon.png"/>
+ <name>smokeapp1</name>
+ <tizen:profile name="mobile"/>
+</widget>
--- /dev/null
+# Target - sources
+SET(SRCS
+ rds_parser.cc
+ step/step_check_settings_level.cc
+ step/step_check_wgt_background_category.cc
+ step/step_create_symbolic_link.cc
+ step/step_encrypt_resources.cc
+ step/step_generate_xml.cc
+ step/step_parse.cc
+ step/step_remove_encryption_data.cc
+ step/step_parse_recovery.cc
+ step/step_rds_parse.cc
+ step/step_rds_modify.cc
+ step/step_wgt_create_icons.cc
+ step/step_wgt_create_storage_directories.cc
+ step/step_wgt_copy_storage_directories.cc
+ step/step_wgt_resource_directory.cc
+ step/step_add_default_privileges.cc
+ wgt_app_query_interface.cc
+ wgt_installer.cc
+)
+
+IF(WRT_LAUNCHER)
+ ADD_DEFINITIONS("-DWRT_LAUNCHER=\"${WRT_LAUNCHER}\"")
+ MESSAGE( "WRT LAUNCHER binary path is set to ${WRT_LAUNCHER}")
+ELSE(WRT_LAUNCHER)
+ MESSAGE(FATAL_ERROR, "WRT LAUNCHER binary path is not set")
+ENDIF(WRT_LAUNCHER)
+
+# Target - definition
+ADD_LIBRARY(${TARGET_LIBNAME_WGT} STATIC ${SRCS})
+ADD_EXECUTABLE(${TARGET_WGT_BACKEND} "wgt_backend.cc")
+# Target - includes
+TARGET_INCLUDE_DIRECTORIES(${TARGET_LIBNAME_WGT} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
+TARGET_INCLUDE_DIRECTORIES(${TARGET_WGT_BACKEND} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
+# Target - deps
+APPLY_PKG_CONFIG(${TARGET_LIBNAME_WGT} PUBLIC
+ APP_INSTALLERS_DEPS
+ MANIFEST_HANDLERS_DEPS
+ MANIFEST_PARSER_DEPS
+ PKGMGR_INSTALLER_DEPS
+ ENCRYPTION_DEPS
+ Boost
+)
+
+# Target - in-package deps
+TARGET_LINK_LIBRARIES(${TARGET_WGT_BACKEND} PRIVATE ${TARGET_LIBNAME_WGT})
+
+# Install
+INSTALL(TARGETS ${TARGET_LIBNAME_WGT} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(TARGETS ${TARGET_WGT_BACKEND} DESTINATION ${BINDIR})
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/rds_parser.h"
+
+#include <fstream>
+
+namespace {
+const char kAdd[] = "#add";
+const char kModify[] = "#modify";
+const char kDelete[] = "#delete";
+}
+
+namespace wgt {
+namespace rds_parser {
+
+RDSParser::RDSParser(const std::string& path_to_delta)
+ : path_to_delta_(path_to_delta) {}
+
+bool RDSParser::Parse() {
+ std::vector<std::string>* current_container = nullptr;
+ std::string line;
+
+ std::ifstream file_to_parse(path_to_delta_);
+ if (!file_to_parse.is_open())
+ return false;
+ while (getline(file_to_parse, line)) {
+ if (line.compare(kDelete) == 0) {
+ current_container = &files_to_delete_;
+ continue;
+ }
+ if (line.compare(kAdd) == 0) {
+ current_container = &files_to_add_;
+ continue;
+ }
+ if (line.compare(kModify) == 0) {
+ current_container = &files_to_modify_;
+ continue;
+ }
+ if (current_container)
+ current_container->push_back(line);
+ }
+ file_to_parse.close();
+ return true;
+}
+
+const std::vector<std::string>& RDSParser::files_to_modify() const {
+ return files_to_modify_;
+}
+
+const std::vector<std::string>& RDSParser::files_to_add() const {
+ return files_to_add_;
+}
+
+const std::vector<std::string>& RDSParser::files_to_delete() const {
+ return files_to_delete_;
+}
+
+} // namespace rds_parser
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_RDS_PARSER_H_
+#define WGT_RDS_PARSER_H_
+
+#include <string>
+#include <vector>
+namespace wgt {
+namespace rds_parser {
+
+/**
+ * \brief Parse RDS config file
+ */
+class RDSParser {
+ public:
+ /**
+ * \brief Explicit constructor
+ *
+ * \param path_to_delta path to directory
+ */
+ explicit RDSParser(const std::string& path_to_delta);
+
+ /**
+ * \brief Parse package xml
+ *
+ * \return true if parsing was successful
+ */
+ bool Parse();
+
+ /**
+ * \brief Accessor to vector of files to modify
+ *
+ * \return files to modify
+ */
+ const std::vector<std::string>& files_to_modify() const;
+
+ /**
+ * \brief Accessor to vector of files to add
+ *
+ * \return files to add
+ */
+ const std::vector<std::string>& files_to_add() const;
+
+ /**
+ * \brief Accessor to vector of files to delete
+ *
+ * \return files to delete
+ */
+ const std::vector<std::string>& files_to_delete() const;
+
+ private:
+ std::string path_to_delta_;
+ std::vector<std::string> files_to_modify_;
+ std::vector<std::string> files_to_add_;
+ std::vector<std::string> files_to_delete_;
+};
+
+} // namespace rds_parser
+} // namespace wgt
+
+#endif // WGT_RDS_PARSER_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_add_default_privileges.h"
+
+#include <pkgmgrinfo_basic.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+
+namespace {
+
+const char kPrivForWebApp[] =
+ "http://tizen.org/privilege/internal/webappdefault";
+
+} // namespace
+
+namespace wgt {
+namespace security {
+
+common_installer::Step::Status StepAddDefaultPrivileges::precheck() {
+ if (!context_->manifest_data.get()) {
+ LOG(ERROR) << "Manifest data is not set";
+ return Status::ERROR;
+ }
+ return Status::OK;
+}
+
+common_installer::Step::Status StepAddDefaultPrivileges::process() {
+ manifest_x* m = context_->manifest_data.get();
+ m->privileges = g_list_append(m->privileges, strdup(kPrivForWebApp));
+ return Status::OK;
+}
+
+} // namespace security
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_ADD_DEFAULT_PRIVILEGES_H_
+#define WGT_STEP_STEP_ADD_DEFAULT_PRIVILEGES_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+namespace wgt {
+namespace security {
+
+/**
+ * \brief Step that add default privileges during installation
+ */
+class StepAddDefaultPrivileges : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Add default privileges
+ *
+ * \return Status::OK
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Check requirements for this step
+ *
+ * \return Status::ERROR when rmanifest data are missing,
+ * Status::OK otherwise
+ */
+ Status precheck() override;
+
+ SCOPE_LOG_TAG(AddDefaultPrivileges)
+};
+
+} // namespace security
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_ADD_DEFAULT_PRIVILEGES_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_check_settings_level.h"
+
+#include <manifest_handlers/setting_handler.h>
+#include <manifest_parser/utils/logging.h>
+
+#include <map>
+
+#include "wgt/wgt_backend_data.h"
+
+namespace {
+
+bool ValidateSettingsForLevel(common_installer::PrivilegeLevel level,
+ const wgt::parse::SettingInfo& settings) {
+ if (settings.background_vibration()) {
+ common_installer::PrivilegeLevel required_level =
+ common_installer::PrivilegeLevel::PARTNER;
+ if (!common_installer::SatifiesPrivilegeLevel(required_level, level)) {
+ LOG(ERROR) << "background_vibration requires visibility level: "
+ << common_installer::PrivilegeLevelToString(required_level);
+ return false;
+ }
+ LOG(INFO) << "Setting: 'background-vibration' allowed";
+ }
+ return true;
+}
+
+} // namespace
+
+namespace wgt {
+namespace security {
+
+common_installer::Step::Status StepCheckSettingsLevel::process() {
+ if (!ValidateSettingsForLevel(context_->privilege_level.get(),
+ static_cast<WgtBackendData*>(
+ context_->backend_data.get())->settings.get())) {
+ return Status::ERROR;
+ }
+ LOG(INFO) << "Settings privilege level checked";
+ return Status::OK;
+}
+
+} // namespace security
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_CHECK_SETTINGS_LEVEL_H_
+#define WGT_STEP_STEP_CHECK_SETTINGS_LEVEL_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+namespace wgt {
+namespace security {
+
+/**
+ * \brief Step that check privileges level for settings
+ */
+class StepCheckSettingsLevel : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Check privileges level for settings
+ *
+ * \return Status::ERROR when invalid privileges detected,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ SCOPE_LOG_TAG(CheckSettingsLevel)
+};
+
+} // namespace security
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_CHECK_SETTINGS_LEVEL_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_check_wgt_background_category.h"
+
+#include <common/installer_context.h>
+#include <manifest_handlers/setting_handler.h>
+
+#include "wgt/wgt_backend_data.h"
+
+namespace {
+namespace ci_sec = common_installer::security;
+} // namespace
+
+namespace wgt {
+namespace security {
+
+StepCheckWgtBackgroundCategory::StepCheckWgtBackgroundCategory(
+ common_installer::InstallerContext* context) :
+ ci_sec::StepCheckBackgroundCategory(context) {}
+
+bool StepCheckWgtBackgroundCategory::GetBackgroundSupport() {
+ const wgt::parse::SettingInfo& settings = static_cast<WgtBackendData*>(
+ context_->backend_data.get())->settings.get();
+ return settings.background_support_enabled();
+}
+
+} // namespace security
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_CHECK_WGT_BACKGROUND_CATEGORY_H_
+#define WGT_STEP_STEP_CHECK_WGT_BACKGROUND_CATEGORY_H_
+
+#include <common/step/step_check_background_category.h>
+#include <manifest_parser/utils/version_number.h>
+
+namespace wgt {
+namespace security {
+
+/**
+ * \brief This step check background category value and modify it depending on
+ * required version, cert level, background support, and value itself
+ */
+class StepCheckWgtBackgroundCategory :
+ public common_installer::security::StepCheckBackgroundCategory {
+ public:
+ explicit StepCheckWgtBackgroundCategory(
+ common_installer::InstallerContext* context);
+
+ protected:
+ bool GetBackgroundSupport() override;
+};
+
+} // namespace security
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_CHECK_WGT_BACKGROUND_CATEGORY_H_
--- /dev/null
+/* 2014, Copyright © Eurogiciel Coporation, APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_create_symbolic_link.h"
+
+#include <pkgmgr-info.h>
+#include <unistd.h>
+
+#include <boost/filesystem.hpp>
+#include <common/utils/file_util.h>
+#include <common/utils/glist_range.h>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+#include <string>
+
+
+namespace {
+
+const char kWrtServiceBinaryPath[] = "/usr/bin/wrt-service";
+
+} // namespace
+
+namespace wgt {
+namespace filesystem {
+
+namespace bf = boost::filesystem;
+
+common_installer::Step::Status StepCreateSymbolicLink::process() {
+ assert(context_->manifest_data.get());
+ boost::system::error_code error;
+ for (application_x* app :
+ GListRange<application_x*>(context_->manifest_data.get()->application)) {
+ // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
+ bf::path exec_path =
+ context_->pkg_path.get()
+ / bf::path("bin");
+ common_installer::CreateDir(exec_path);
+
+ exec_path /= bf::path(app->appid);
+
+ if (strcmp(app->component_type, "uiapp") == 0) {
+ bf::create_symlink(bf::path(WRT_LAUNCHER), exec_path, error);
+ } else {
+ bf::create_symlink(kWrtServiceBinaryPath, exec_path, error);
+ }
+ if (error) {
+ LOG(ERROR) << "Failed to set symbolic link "
+ << boost::system::system_error(error).what();
+ return Step::Status::ERROR;
+ }
+ }
+ LOG(DEBUG) << "Successfully parse tizen manifest xml";
+
+ return Status::OK;
+}
+
+common_installer::Step::Status StepCreateSymbolicLink::undo() {
+ for (application_x* app :
+ GListRange<application_x*>(context_->manifest_data.get()->application)) {
+ bf::path exec_path = context_->pkg_path.get() / "bin" / app->appid;
+ if (bf::exists(exec_path))
+ bf::remove_all(exec_path);
+ }
+ return Status::OK;
+}
+
+} // namespace filesystem
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_CREATE_SYMBOLIC_LINK_H_
+#define WGT_STEP_STEP_CREATE_SYMBOLIC_LINK_H_
+
+#include <boost/filesystem.hpp>
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief Step that create symbolic link to application
+ */
+class StepCreateSymbolicLink : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Create symbolic link
+ *
+ * \return Status::ERROR when failed to create symbolic link,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Delete created symbolic link
+ *
+ * \return Status::OK
+ */
+ Status undo() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ SCOPE_LOG_TAG(SymbolicLink)
+};
+
+} // namespace filesystem
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_CREATE_SYMBOLIC_LINK_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_encrypt_resources.h"
+
+#include <web_app_enc.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/utils/file_util.h>
+
+#include <manifest_parser/utils/logging.h>
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <set>
+#include <string>
+
+
+namespace {
+
+const std::set<std::string> encryptSet { ".html", ".htm", ".css", ".js"};
+
+} // namespace
+
+
+namespace wgt {
+namespace encrypt {
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+common_installer::Step::Status StepEncryptResources::precheck() {
+ backend_data_ = static_cast<WgtBackendData*>(context_->backend_data.get());
+ if (!backend_data_) {
+ LOG(ERROR) << "no backend data";
+ return common_installer::Step::Status::ERROR;
+ }
+
+ input_ = context_->unpacked_dir_path.get();
+
+ if (input_.empty()) {
+ LOG(ERROR) << "unpacked_dir_path attribute is empty";
+ return Step::Status::INVALID_VALUE;
+ }
+ if (!bf::exists(input_)) {
+ LOG(ERROR) << "unpacked_dir_path (" << input_ << ") path does not exist";
+ return Step::Status::INVALID_VALUE;
+ }
+
+ return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepEncryptResources::process() {
+ if (!backend_data_->settings.get().encryption_enabled()) {
+ LOG(DEBUG) << "no encryption";
+ return common_installer::Step::Status::OK;
+ }
+ LOG(DEBUG) << "Encrypting";
+
+ if (!Encrypt(input_)) {
+ LOG(ERROR) << "Error during encryption";
+ return common_installer::Step::Status::ERROR;
+ }
+
+ return common_installer::Step::Status::OK;
+}
+
+bool StepEncryptResources::Encrypt(const bf::path &src) {
+ // traversing through src dir (recurrence if subdir found)
+ // for every file found, check if it should be encrypted (ToBeEncrypted)
+ // if yes, encrypt it (and replace original one)
+ // if not, leave it
+ for (bf::directory_iterator file(src);
+ file != bf::directory_iterator();
+ ++file) {
+ bs::error_code error_code;
+ bf::path current(file->path());
+
+ bool is_dir = bf::is_directory(current, error_code);
+ if (error_code)
+ return false;
+ if (is_dir) {
+ if (!Encrypt(current))
+ return false;
+ continue;
+ }
+
+ bool is_sym = bf::is_symlink(current, error_code);
+ if (error_code)
+ return false;
+ if (is_sym)
+ continue; // TODO(p.sikorski) is it enough?
+
+ // it is regular file (not dir, not symlink)
+ if (ToBeEncrypted(current)) {
+ LOG(INFO) << "File for encryption: " << current;
+ if (!EncryptFile(current))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool StepEncryptResources::EncryptFile(const bf::path &src) {
+ FILE *input = fopen(src.string().c_str(), "rb");
+ if (!input) {
+ LOG(ERROR) << "Cannot open file for encryption: " << src;
+ return false;
+ }
+
+ // read size
+ fseek(input , 0 , SEEK_END);
+ size_t length = ftell(input);
+
+ // don't encrypt empty files because libwebappenc doesn't support it
+ if (length == 0) {
+ fclose(input);
+ return true;
+ }
+
+ rewind(input);
+
+ char *input_buffer = new char[length];
+ if (length != fread(input_buffer, sizeof(char), length, input)) {
+ LOG(ERROR) << "Read error, file: " << src;
+ fclose(input);
+ delete []input_buffer;
+ return false;
+ }
+ fclose(input);
+
+ unsigned char* encrypted_data = nullptr;
+ size_t enc_data_len = 0;
+ // TODO(p.sikorski) check if it is Preloaded
+ wae_app_type_e enc_type =
+ context_->request_mode.get() == common_installer::RequestMode::GLOBAL ?
+ WAE_DOWNLOADED_GLOBAL_APP : WAE_DOWNLOADED_NORMAL_APP;
+
+
+ int ret = wae_encrypt_web_application(
+ context_->pkgid.get().c_str(),
+ enc_type,
+ reinterpret_cast<const unsigned char*>(input_buffer),
+ length,
+ &encrypted_data,
+ &enc_data_len);
+ delete []input_buffer;
+ if (WAE_ERROR_NONE != ret) {
+ switch (ret) {
+ case WAE_ERROR_INVALID_PARAMETER:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_INVALID_PARAMETER";
+ break;
+ case WAE_ERROR_PERMISSION_DENIED:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_PERMISSION_DENIED";
+ break;
+ case WAE_ERROR_NO_KEY:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_NO_KEY";
+ break;
+ case WAE_ERROR_KEY_MANAGER:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_KEY_MANAGER";
+ break;
+ case WAE_ERROR_CRYPTO:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_CRYPTO";
+ break;
+ case WAE_ERROR_UNKNOWN:
+ LOG(ERROR) << "Error during encrypting: WAE_ERROR_UNKNOWN";
+ break;
+ default:
+ LOG(ERROR) << "Error during encrypting: UNKNOWN";
+ break;
+ }
+ return false;
+ }
+
+ // original file is treated as destination!
+ FILE *output = fopen(src.string().c_str(), "wb");
+ if (!output) {
+ LOG(ERROR) << "Cannot create encrypted file: " << src;
+ free(encrypted_data);
+ return false;
+ }
+
+ if (enc_data_len != fwrite(reinterpret_cast<const char*>(encrypted_data),
+ sizeof(char),
+ enc_data_len,
+ output)) {
+ LOG(ERROR) << "Write error, file: " << src;
+ free(encrypted_data);
+ fclose(output);
+ return false;
+ }
+
+
+ fclose(output);
+ free(encrypted_data);
+ return true;
+}
+
+bool StepEncryptResources::ToBeEncrypted(const bf::path &file) {
+ size_t found_key = file.string().rfind(".");
+ if (std::string::npos != found_key) {
+ std::string mimeType = file.string().substr(found_key);
+ std::transform(mimeType.begin(), mimeType.end(), mimeType.begin(),
+ ::tolower);
+ return encryptSet.count(mimeType) > 0;
+ }
+ return false;
+}
+
+} // namespace encrypt
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
+#define WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <common/step/step.h>
+#include <manifest_parser/utils/logging.h>
+
+#include "wgt/wgt_backend_data.h"
+
+namespace wgt {
+namespace encrypt {
+
+/**
+ * \brief Step that encrypt application resources files if flagged to do so
+ */
+class StepEncryptResources : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Encrypt files
+ *
+ * \return Status::ERROR when error occurred during encryption,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Check requirements for this step
+ *
+ * \return Status::ERROR when manifest data are missing,
+ * Status::INVALID_VALUE when requirements are not meet,
+ * Status::OK otherwise
+ */
+ Status precheck() override;
+
+ private:
+ bool Encrypt(const boost::filesystem::path &src);
+ bool EncryptFile(const boost::filesystem::path &src);
+ bool ToBeEncrypted(const boost::filesystem::path &file);
+ WgtBackendData* backend_data_;
+ boost::filesystem::path input_;
+ SCOPE_LOG_TAG(EncryptResources)
+};
+} // namespace encrypt
+} // namespace wgt
+#endif // WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
--- /dev/null
+/* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_generate_xml.h"
+
+#include <boost/filesystem/path.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/utils/file_util.h>
+#include <common/utils/glist_range.h>
+
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_parser.h>
+#include <tzplatform_config.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <cstring>
+#include <string>
+
+
+namespace bs = boost::system;
+namespace bf = boost::filesystem;
+
+namespace {
+
+void WriteUIApplicationAttributes(
+ xmlTextWriterPtr writer, application_x *app) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
+ BAD_CAST "true");
+ if (app->nodisplay)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
+ BAD_CAST app->nodisplay);
+ if (app->multiple)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "multiple",
+ BAD_CAST app->multiple);
+ if (app->launch_mode && strlen(app->launch_mode))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "launch_mode",
+ BAD_CAST app->launch_mode);
+ if (app->ui_gadget && strlen(app->ui_gadget))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "ui-gadget",
+ BAD_CAST app->ui_gadget);
+ if (app->submode && strlen(app->submode))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "submode",
+ BAD_CAST app->submode);
+ if (app->submode_mainid && strlen(app->submode_mainid))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "submode-mainid",
+ BAD_CAST app->submode_mainid);
+ if (app->indicatordisplay && strlen(app->indicatordisplay))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "indicatordisplay",
+ BAD_CAST app->indicatordisplay);
+ if (app->portraitimg && strlen(app->portraitimg))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "portrait-effectimage",
+ BAD_CAST app->portraitimg);
+ if (app->landscapeimg && strlen(app->landscapeimg))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "landscape-effectimage",
+ BAD_CAST app->landscapeimg);
+ if (app->effectimage_type && strlen(app->effectimage_type))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "effectimage-type",
+ BAD_CAST app->effectimage_type);
+ if (app->hwacceleration && strlen(app->hwacceleration))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "hwacceleration",
+ BAD_CAST app->hwacceleration);
+}
+
+void WriteServiceApplicationAttributes(
+ xmlTextWriterPtr writer, application_x *app) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "auto-restart",
+ BAD_CAST(app->autorestart ? app->autorestart : "false"));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "on-boot",
+ BAD_CAST(app->onboot ? app->onboot : "false"));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
+ BAD_CAST "false");
+}
+
+void WriteWidgetApplicationAttributes(
+ xmlTextWriterPtr writer, application_x *app) {
+ if (app->nodisplay)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay",
+ BAD_CAST app->nodisplay);
+ if (app->multiple)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "multiple",
+ BAD_CAST app->multiple);
+}
+
+} // namespace
+
+namespace wgt {
+namespace pkgmgr {
+
+common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml(
+ application_x* app, xmlTextWriterPtr writer, AppCompType type) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "appid", BAD_CAST app->appid);
+
+ // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
+ bf::path exec_path = context_->pkg_path.get()
+ / bf::path("bin") / bf::path(app->appid);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "exec",
+ BAD_CAST exec_path.string().c_str());
+ if (app->type)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST app->type);
+ else
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST "capp");
+
+ if (app->process_pool && strlen(app->process_pool))
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "process-pool",
+ BAD_CAST app->process_pool);
+ // app-specific attributes
+ switch (type) {
+ case AppCompType::UIAPP:
+ WriteServiceApplicationAttributes(writer, app);
+ break;
+ case AppCompType::SVCAPP:
+ WriteUIApplicationAttributes(writer, app);
+ break;
+ case AppCompType::WIDGETAPP:
+ WriteWidgetApplicationAttributes(writer, app);
+ break;
+ }
+
+ for (label_x* label : GListRange<label_x*>(app->label)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "label");
+ if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+ BAD_CAST label->lang);
+ }
+ xmlTextWriterWriteString(writer, BAD_CAST label->name);
+ xmlTextWriterEndElement(writer);
+ }
+
+ // icon is renamed to <appid.png>
+ if (app->icon) {
+ icon_x* iconx = reinterpret_cast<icon_x*>(app->icon->data);
+ bf::path app_icon = context_->pkg_path.get();
+ // TODO(t.iwanek): type should not be used here
+ if (context_->pkg_type.get() == "wgt") {
+ app_icon /= "res/wgt";
+ } else {
+ app_icon /= "shared/res";
+ }
+ app_icon /= iconx->text;
+ bf::path icon = app->appid;
+ if (app_icon.has_extension())
+ icon += app_icon.extension();
+ else
+ icon += bf::path(".png");
+
+ if (bf::exists(app_icon)) {
+ xmlTextWriterWriteFormatElement(writer, BAD_CAST "icon",
+ "%s", BAD_CAST icon.c_str());
+ }
+ } else {
+ // Default icon setting is role of the platform
+ LOG(DEBUG) << "Icon was not found in package";
+ }
+
+ for (image_x* image : GListRange<image_x*>(app->image)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "image");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
+ BAD_CAST image->name);
+ if (image->lang && strcmp(DEFAULT_LOCALE, image->lang) != 0) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+
+ BAD_CAST image->lang);
+ }
+ if (image->section)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
+ BAD_CAST image->section);
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (appcontrol_x* appc : GListRange<appcontrol_x*>(app->appcontrol)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "app-control");
+
+ if (appc->operation) {
+ xmlTextWriterStartElement(writer, BAD_CAST "operation");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
+ BAD_CAST appc->operation);
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (appc->uri) {
+ xmlTextWriterStartElement(writer, BAD_CAST "uri");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
+ BAD_CAST appc->uri);
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (appc->mime) {
+ xmlTextWriterStartElement(writer, BAD_CAST "mime");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
+ BAD_CAST appc->mime);
+ xmlTextWriterEndElement(writer);
+ }
+
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (datacontrol_x* datacontrol :
+ GListRange<datacontrol_x*>(app->datacontrol)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "datacontrol");
+ if (datacontrol->access) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "access",
+ BAD_CAST datacontrol->access);
+ }
+ if (datacontrol->providerid) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
+ BAD_CAST datacontrol->providerid);
+ }
+ if (datacontrol->type) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
+ BAD_CAST datacontrol->type);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (metadata_x* meta : GListRange<metadata_x*>(app->metadata)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "metadata");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "key",
+ BAD_CAST meta->key);
+ if (meta->value)
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
+ BAD_CAST meta->value);
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (const char* category : GListRange<char*>(app->category)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "category");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST category);
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (const char* background_category : GListRange<char*>(
+ app->background_category)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "background-category");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "value",
+ BAD_CAST background_category);
+ xmlTextWriterEndElement(writer);
+ }
+
+ return Step::Status::OK;
+}
+
+common_installer::Step::Status StepGenerateXml::precheck() {
+ if (!context_->manifest_data.get()) {
+ LOG(ERROR) << "manifest_data attribute is empty";
+ return Step::Status::INVALID_VALUE;
+ }
+ if (context_->pkgid.get().empty()) {
+ LOG(ERROR) << "pkgid attribute is empty";
+ return Step::Status::INVALID_VALUE; }
+
+ if (!context_->manifest_data.get()->application) {
+ LOG(ERROR) << "No application in package";
+ return Step::Status::INVALID_VALUE;
+ }
+ // TODO(p.sikorski) check context_->uid.get()
+
+ return Step::Status::OK;
+}
+
+common_installer::Step::Status StepGenerateXml::process() {
+ bf::path xml_path = bf::path(getUserManifestPath(context_->uid.get()))
+ / bf::path(context_->pkgid.get());
+ xml_path += ".xml";
+ context_->xml_path.set(xml_path.string());
+
+ bs::error_code error;
+ if (!bf::exists(xml_path.parent_path(), error)) {
+ if (!common_installer::CreateDir(xml_path.parent_path())) {
+ LOG(ERROR) <<
+ "Directory for manifest xml is missing and cannot be created";
+ return Status::ERROR;
+ }
+ }
+
+ xmlTextWriterPtr writer;
+
+ writer = xmlNewTextWriterFilename(context_->xml_path.get().c_str(), 0);
+ if (!writer) {
+ LOG(ERROR) << "Failed to create new file";
+ return Step::Status::ERROR;
+ }
+
+ xmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
+
+ xmlTextWriterSetIndent(writer, 1);
+
+ // add manifest Element
+ xmlTextWriterStartElement(writer, BAD_CAST "manifest");
+
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
+ BAD_CAST "http://tizen.org/ns/packages");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "package",
+ BAD_CAST context_->manifest_data.get()->package);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
+ BAD_CAST context_->manifest_data.get()->type);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
+ BAD_CAST context_->manifest_data.get()->version);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "api-version",
+ BAD_CAST context_->manifest_data.get()->api_version);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "nodisplay-setting",
+ BAD_CAST context_->manifest_data.get()->nodisplay_setting);
+
+ for (label_x* label :
+ GListRange<label_x*>(context_->manifest_data.get()->label)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "label");
+ if (label->lang && strcmp(DEFAULT_LOCALE, label->lang) != 0) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+ BAD_CAST label->lang);
+ }
+ xmlTextWriterWriteString(writer, BAD_CAST label->name);
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (author_x* author :
+ GListRange<author_x*>(context_->manifest_data.get()->author)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "author");
+ if (author->email && strlen(author->email)) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "email",
+ BAD_CAST author->email);
+ }
+ if (author->href && strlen(author->href)) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "href",
+ BAD_CAST author->href);
+ }
+ xmlTextWriterWriteString(writer, BAD_CAST author->text);
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (description_x* description :
+ GListRange<description_x*>(context_->manifest_data.get()->description)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "description");
+ if (description->lang && strcmp(DEFAULT_LOCALE, description->lang) != 0) {
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+ BAD_CAST description->lang);
+ }
+ xmlTextWriterWriteString(writer, BAD_CAST description->text);
+ xmlTextWriterEndElement(writer);
+ }
+
+ // add application
+ for (application_x* app :
+ GListRange<application_x*>(context_->manifest_data.get()->application)) {
+ AppCompType type;
+ if (strcmp(app->component_type, "uiapp") == 0) {
+ type = AppCompType::UIAPP;
+ xmlTextWriterStartElement(writer, BAD_CAST "ui-application");
+ } else if (strcmp(app->component_type, "svcapp") == 0) {
+ type = AppCompType::SVCAPP;
+ xmlTextWriterStartElement(writer, BAD_CAST "service-application");
+ } else if (strcmp(app->component_type, "widgetapp") == 0) {
+ type = AppCompType::WIDGETAPP;
+ xmlTextWriterStartElement(writer, BAD_CAST "widget-application");
+ } else {
+ LOG(ERROR) << "Unknown application component_type";
+ xmlFreeTextWriter(writer);
+ return Status::ERROR;
+ }
+ GenerateApplicationCommonXml(app, writer, type);
+ xmlTextWriterEndElement(writer);
+ }
+
+ // add privilege element
+ if (context_->manifest_data.get()->privileges) {
+ xmlTextWriterStartElement(writer, BAD_CAST "privileges");
+ for (const char* priv :
+ GListRange<char*>(context_->manifest_data.get()->privileges)) {
+ xmlTextWriterWriteFormatElement(writer, BAD_CAST "privilege",
+ "%s", BAD_CAST priv);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+
+ const auto& accounts =
+ context_->manifest_plugins_data.get().account_info.get().accounts();
+ if (!accounts.empty()) {
+ xmlTextWriterStartElement(writer, BAD_CAST "account");
+ // add account info
+ for (auto& account : accounts) {
+ xmlTextWriterStartElement(writer, BAD_CAST "account-provider");
+
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
+ BAD_CAST account.appid.c_str());
+
+ if (!account.providerid.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "providerid",
+ BAD_CAST account.providerid.c_str());
+
+ if (account.multiple_account_support)
+ xmlTextWriterWriteAttribute(writer,
+ BAD_CAST "multiple-accounts-support",
+ BAD_CAST "true");
+ for (auto& icon_pair : account.icon_paths) {
+ xmlTextWriterStartElement(writer, BAD_CAST "icon");
+ if (icon_pair.first == "AccountSmall")
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
+ BAD_CAST "account-small");
+ else
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "section",
+ BAD_CAST "account");
+ xmlTextWriterWriteString(writer, BAD_CAST icon_pair.second.c_str());
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (auto& name_pair : account.names) {
+ xmlTextWriterStartElement(writer, BAD_CAST "label");
+ if (!name_pair.second.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+ BAD_CAST name_pair.second.c_str());
+ xmlTextWriterWriteString(writer, BAD_CAST name_pair.first.c_str());
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (auto& capability : account.capabilities) {
+ xmlTextWriterWriteFormatElement(writer, BAD_CAST "capability",
+ "%s", BAD_CAST capability.c_str());
+ }
+
+ xmlTextWriterEndElement(writer);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+
+ for (const char* profile :
+ GListRange<char*>(context_->manifest_data.get()->deviceprofile)) {
+ xmlTextWriterStartElement(writer, BAD_CAST "profile");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
+ BAD_CAST profile);
+ xmlTextWriterEndElement(writer);
+ }
+
+ const auto& shortcuts =
+ context_->manifest_plugins_data.get().shortcut_info.get();
+ if (!shortcuts.empty()) {
+ xmlTextWriterStartElement(writer, BAD_CAST "shortcut-list");
+ for (auto& shortcut : shortcuts) {
+ xmlTextWriterStartElement(writer, BAD_CAST "shortcut");
+ if (!shortcut.app_id.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "appid",
+ BAD_CAST shortcut.app_id.c_str());
+ if (!shortcut.app_id.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_data",
+ BAD_CAST shortcut.extra_data.c_str());
+ if (!shortcut.app_id.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "extra_key",
+ BAD_CAST shortcut.extra_key.c_str());
+ if (!shortcut.icon.empty()) {
+ xmlTextWriterStartElement(writer, BAD_CAST "icon");
+ xmlTextWriterWriteString(writer, BAD_CAST shortcut.icon.c_str());
+ xmlTextWriterEndElement(writer);
+ }
+ for (auto& label : shortcut.labels) {
+ xmlTextWriterStartElement(writer, BAD_CAST "label");
+ if (!label.first.empty())
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
+ BAD_CAST label.first.c_str());
+ xmlTextWriterWriteString(writer, BAD_CAST label.second.c_str());
+ xmlTextWriterEndElement(writer);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+
+ xmlTextWriterEndElement(writer);
+
+ xmlTextWriterEndDocument(writer);
+ xmlFreeTextWriter(writer);
+
+ if (pkgmgr_parser_check_manifest_validation(
+ context_->xml_path.get().c_str()) != 0) {
+ LOG(ERROR) << "Manifest is not valid";
+ return Step::Status::ERROR;
+ }
+
+ LOG(DEBUG) << "Successfully create manifest xml "
+ << context_->xml_path.get();
+ return Status::OK;
+}
+
+common_installer::Step::Status StepGenerateXml::undo() {
+ bs::error_code error;
+ if (bf::exists(context_->xml_path.get()))
+ bf::remove_all(context_->xml_path.get(), error);
+ return Status::OK;
+}
+
+} // namespace pkgmgr
+} // namespace wgt
--- /dev/null
+/* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_GENERATE_XML_H_
+#define WGT_STEP_STEP_GENERATE_XML_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <libxml/xmlwriter.h>
+
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+namespace wgt {
+namespace pkgmgr {
+
+class StepGenerateXml : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ Status process() override;
+ Status clean() override { return Status::OK; }
+ Status undo() override;
+ Status precheck() override;
+
+ private:
+ enum class AppCompType {
+ UIAPP,
+ SVCAPP,
+ WIDGETAPP
+ };
+
+ Step::Status GenerateApplicationCommonXml(application_x* app,
+ xmlTextWriterPtr writer,
+ AppCompType type);
+
+ SCOPE_LOG_TAG(GenerateXML)
+};
+
+} // namespace pkgmgr
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_GENERATE_XML_H_
--- /dev/null
+/* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_parse.h"
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+#include <common/utils/glist_range.h>
+#include <manifest_handlers/account_handler.h>
+#include <manifest_handlers/app_control_handler.h>
+#include <manifest_handlers/application_icons_handler.h>
+#include <manifest_handlers/application_manifest_constants.h>
+#include <manifest_handlers/background_category_handler.h>
+#include <manifest_handlers/category_handler.h>
+#include <manifest_handlers/content_handler.h>
+#include <manifest_handlers/metadata_handler.h>
+#include <manifest_handlers/service_handler.h>
+#include <manifest_handlers/setting_handler.h>
+#include <manifest_handlers/tizen_application_handler.h>
+#include <manifest_handlers/widget_handler.h>
+
+#include <pkgmgr/pkgmgr_parser.h>
+
+#include <string.h>
+
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "wgt/wgt_backend_data.h"
+
+namespace {
+
+const std::string kManifestVersion = "1.0.0";
+const char kTizenPackageXmlNamespace[] = "http://tizen.org/ns/packages";
+
+GList* GenerateMetadataListX(const wgt::parse::MetaDataInfo& meta_info) {
+ GList* list = nullptr;
+ for (auto& meta : meta_info.metadata()) {
+ metadata_x* new_meta =
+ static_cast<metadata_x*>(calloc(1, sizeof(metadata_x)));
+ new_meta->key = strdup(meta.first.c_str());
+ if (!meta.second.empty())
+ new_meta->value = strdup(meta.second.c_str());
+ list = g_list_append(list, new_meta);
+ }
+ return list;
+}
+
+void SetApplicationXDefaults(application_x* application) {
+ application->ambient_support = strdup("false");
+ application->effectimage_type = strdup("image");
+ application->enabled = strdup("true");
+ application->guestmode_visibility = strdup("true");
+ application->hwacceleration = strdup("default");
+ application->indicatordisplay = strdup("true");
+ application->launchcondition = strdup("false");
+ application->permission_type = strdup("normal");
+ application->process_pool = strdup("false");
+ application->recentimage = strdup("false");
+ application->screenreader = strdup("use-system-setting");
+ application->submode = strdup("false");
+ application->support_disable = strdup("false");
+ application->taskmanage = strdup("true");
+ application->ui_gadget = strdup("false");
+}
+
+} // namespace
+
+namespace wgt {
+namespace parse {
+
+namespace app_keys = wgt::application_widget_keys;
+namespace sc = std::chrono;
+
+StepParse::StepParse(common_installer::InstallerContext* context,
+ bool check_start_file)
+ : Step(context),
+ check_start_file_(check_start_file) {
+}
+
+std::set<std::string> StepParse::ExtractPrivileges(
+ std::shared_ptr<const PermissionsInfo> perm_info) const {
+ return perm_info->GetAPIPermissions();
+}
+
+const std::string& StepParse::GetPackageVersion(
+ const std::string& manifest_version) {
+ if (!manifest_version.empty())
+ return manifest_version;
+ return kManifestVersion;
+}
+
+bool StepParse::FillInstallationInfo(manifest_x* manifest) {
+ manifest->root_path = strdup(
+ (context_->root_application_path.get() / manifest->package).c_str());
+ manifest->installed_time =
+ strdup(std::to_string(sc::system_clock::to_time_t(
+ sc::system_clock::now())).c_str());
+ return true;
+}
+
+bool StepParse::FillIconPaths(manifest_x* manifest) {
+ std::shared_ptr<const ApplicationIconsInfo> icons_info =
+ std::static_pointer_cast<const ApplicationIconsInfo>(
+ parser_->GetManifestData(app_keys::kIconsKey));
+ if (icons_info.get()) {
+ for (auto& application_icon : icons_info->icons()) {
+ icon_x* icon = reinterpret_cast<icon_x*> (calloc(1, sizeof(icon_x)));
+ icon->text = strdup(application_icon.path().c_str());
+ icon->lang = strdup(DEFAULT_LOCALE);
+ manifest->icon = g_list_append(manifest->icon, icon);
+ }
+ }
+ return true;
+}
+
+bool StepParse::FillWidgetInfo(manifest_x* manifest) {
+ std::shared_ptr<const WidgetInfo> wgt_info =
+ std::static_pointer_cast<const WidgetInfo>(parser_->GetManifestData(
+ app_keys::kWidgetKey));
+ if (!wgt_info.get()) {
+ LOG(ERROR) << "Widget info manifest data has not been found.";
+ return false;
+ }
+
+ const std::string& version = wgt_info->version();
+
+ manifest->ns = strdup(kTizenPackageXmlNamespace);
+ manifest->version = strdup(GetPackageVersion(version).c_str());
+
+ for (auto& item : wgt_info->description_set()) {
+ description_x* description = reinterpret_cast<description_x*>
+ (calloc(1, sizeof(description_x)));
+ description->text = strdup(item.second.c_str());
+ description->lang = !item.first.empty() ?
+ strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
+ manifest->description = g_list_append(manifest->description, description);
+ }
+
+ for (auto& item : wgt_info->name_set()) {
+ label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
+ label->name = strdup(item.second.c_str());
+ label->text = strdup(item.second.c_str());
+ label->lang = !item.first.empty() ?
+ strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
+ manifest->label = g_list_append(manifest->label, label);
+ }
+
+ manifest->type = strdup("wgt");
+ manifest->appsetting = strdup("false");
+ manifest->nodisplay_setting = strdup("false");
+
+ // For wgt package use the long name
+ for (auto& item : wgt_info->name_set()) {
+ application_x* app =
+ reinterpret_cast<application_x*>(manifest->application->data);
+ label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
+ label->name = strdup(item.second.c_str());
+ label->text = strdup(item.second.c_str());
+ label->lang = !item.first.empty() ?
+ strdup(item.first.c_str()) : strdup(DEFAULT_LOCALE);
+ app->label = g_list_append(app->label, label);
+ }
+
+ author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
+ if (!wgt_info->author().empty())
+ author->text = strdup(wgt_info->author().c_str());
+ if (!wgt_info->author_email().empty())
+ author->email = strdup(wgt_info->author_email().c_str());
+ if (!wgt_info->author_href().empty())
+ author->href = strdup(wgt_info->author_href().c_str());
+ author->lang = strdup(DEFAULT_LOCALE);
+ manifest->author = g_list_append(manifest->author, author);
+
+ std::shared_ptr<const SettingInfo> settings_info =
+ std::static_pointer_cast<const SettingInfo>(
+ parser_->GetManifestData(
+ wgt::application_widget_keys::kTizenSettingKey));
+ if (settings_info) {
+ switch (settings_info->install_location()) {
+ case wgt::parse::SettingInfo::InstallLocation::AUTO: {
+ manifest->installlocation = strdup("auto");
+ break;
+ }
+ case wgt::parse::SettingInfo::InstallLocation::INTERNAL: {
+ manifest->installlocation = strdup("internal-only");
+ break;
+ }
+ case wgt::parse::SettingInfo::InstallLocation::EXTERNAL: {
+ manifest->installlocation = strdup("prefer-external");
+ break;
+ }
+ }
+ } else {
+ manifest->installlocation = strdup("auto");
+ }
+
+ return true;
+}
+
+bool StepParse::FillUIApplicationInfo(manifest_x* manifest) {
+ std::shared_ptr<const TizenApplicationInfo> app_info =
+ std::static_pointer_cast<const TizenApplicationInfo>(
+ parser_->GetManifestData(app_keys::kTizenApplicationKey));
+ if (!app_info) {
+ LOG(ERROR) << "Application info manifest data has not been found.";
+ return false;
+ }
+ // application data
+ application_x* application = reinterpret_cast<application_x*>(
+ calloc(1, sizeof(application_x)));
+ application->component_type = strdup("uiapp");
+ application->mainapp = strdup("true");
+ application->nodisplay = strdup("false");
+ application->multiple = strdup("false");
+ application->appid = strdup(app_info->id().c_str());
+ SetApplicationXDefaults(application);
+ application->package = strdup(app_info->package().c_str());
+
+ application->exec =
+ strdup((context_->root_application_path.get() / app_info->package()
+ / "bin" / application->appid).c_str());
+ application->type = strdup("webapp");
+ application->onboot = strdup("false");
+ application->autorestart = strdup("false");
+
+ application->launch_mode = strdup(app_info->launch_mode().c_str());
+ if (manifest->icon) {
+ icon_x* icon = reinterpret_cast<icon_x*>(manifest->icon->data);
+ icon_x* app_icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
+ app_icon->text = strdup(icon->text);
+ app_icon->lang = strdup(icon->lang);
+ application->icon = g_list_append(application->icon, app_icon);
+ }
+ manifest->application = g_list_append(manifest->application, application);
+
+ manifest->package = strdup(app_info->package().c_str());
+ manifest->mainapp_id = strdup(app_info->id().c_str());
+ return true;
+}
+
+bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) {
+ std::shared_ptr<const ServiceList> service_list =
+ std::static_pointer_cast<const ServiceList>(
+ parser_->GetManifestData(app_keys::kTizenServiceKey));
+ if (!service_list)
+ return true;
+ for (auto& service_info : service_list->services) {
+ application_x* application = reinterpret_cast<application_x*>
+ (calloc(1, sizeof(application_x)));
+ application->component_type = strdup("svcapp");
+ application->mainapp = strdup("false");
+ application->nodisplay = strdup("false");
+ application->multiple = strdup("false");
+ application->appid = strdup(service_info.id().c_str());
+ application->exec =
+ strdup((context_->root_application_path.get() / manifest->package
+ / "bin" / application->appid).c_str());
+ application->type = strdup("webapp");
+ application->onboot =
+ service_info.on_boot() ? strdup("true") : strdup("false");
+ application->autorestart =
+ service_info.auto_restart() ? strdup("true") : strdup("false");
+ SetApplicationXDefaults(application);
+ application->package = strdup(manifest->package);
+
+ for (auto& pair : service_info.names()) {
+ label_x* label = reinterpret_cast<label_x*>(calloc(1, sizeof(label_x)));
+ label->lang = !pair.first.empty() ?
+ strdup(pair.first.c_str()) : strdup(DEFAULT_LOCALE);
+ label->name = strdup(pair.second.c_str());
+ label->text = strdup(pair.second.c_str());
+ application->label = g_list_append(application->label, label);
+ }
+
+ if (!service_info.icon().empty()) {
+ icon_x* icon = reinterpret_cast<icon_x*>(calloc(1, sizeof(icon_x)));
+ icon->text = strdup(service_info.icon().c_str());
+ icon->lang = strdup(DEFAULT_LOCALE);
+ application->icon = g_list_append(application->icon, icon);
+ }
+
+ // TODO(t.iwanek): what about description, how is it different from name?
+
+ for (auto& category : service_info.categories()) {
+ application->category = g_list_append(application->category,
+ strdup(category.c_str()));
+ }
+
+ for (auto& pair : service_info.metadata_set()) {
+ metadata_x* item = reinterpret_cast<metadata_x*>(
+ calloc(1, sizeof(metadata_x)));
+ item->key = strdup(pair.first.c_str());
+ if (!pair.second.empty())
+ item->value = strdup(pair.second.c_str());
+ application->metadata = g_list_append(application->metadata, item);
+ }
+
+ manifest->application = g_list_append(manifest->application, application);
+ }
+ return true;
+}
+
+bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) {
+ auto manifest_data = parser_->GetManifestData(
+ app_keys::kTizenBackgroundCategoryKey);
+ std::shared_ptr<const BackgroundCategoryInfoList> bc_list =
+ std::static_pointer_cast<const BackgroundCategoryInfoList>(manifest_data);
+
+ if (!bc_list)
+ return true;
+
+ application_x* app =
+ reinterpret_cast<application_x*>(manifest->application->data);
+
+ for (auto& background_category : bc_list->background_categories) {
+ app->background_category = g_list_append(
+ app->background_category, strdup(background_category.value().c_str()));
+ }
+
+ return true;
+}
+
+bool StepParse::FillAppControl(manifest_x* manifest) {
+ std::shared_ptr<const AppControlInfoList> app_info_list =
+ std::static_pointer_cast<const AppControlInfoList>(
+ parser_->GetManifestData(app_keys::kTizenApplicationAppControlsKey));
+
+ application_x* app =
+ reinterpret_cast<application_x*>(manifest->application->data);
+ if (app_info_list) {
+ for (const auto& control : app_info_list->controls) {
+ appcontrol_x* app_control =
+ static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
+ app_control->operation = strdup(control.operation().c_str());
+ app_control->mime = strdup(control.mime().c_str());
+ app_control->uri = strdup(control.uri().c_str());
+ app->appcontrol = g_list_append(app->appcontrol, app_control);
+ }
+ }
+ return true;
+}
+
+bool StepParse::FillPrivileges(manifest_x* manifest) {
+ std::shared_ptr<const PermissionsInfo> perm_info =
+ std::static_pointer_cast<const PermissionsInfo>(parser_->GetManifestData(
+ app_keys::kTizenPermissionsKey));
+ std::set<std::string> privileges;
+ if (perm_info)
+ privileges = ExtractPrivileges(perm_info);
+
+ for (auto& priv : privileges) {
+ manifest->privileges =
+ g_list_append(manifest->privileges, strdup(priv.c_str()));
+ }
+ return true;
+}
+
+bool StepParse::FillCategories(manifest_x* manifest) {
+ std::shared_ptr<const CategoryInfoList> category_info =
+ std::static_pointer_cast<const CategoryInfoList>(parser_->GetManifestData(
+ app_keys::kTizenCategoryKey));
+ if (!category_info)
+ return true;
+
+ application_x* app =
+ reinterpret_cast<application_x*>(manifest->application->data);
+ // there is one app atm
+ for (auto& category : category_info->categories) {
+ app->category = g_list_append(app->category, strdup(category.c_str()));
+ }
+ return true;
+}
+
+bool StepParse::FillMetadata(manifest_x* manifest) {
+ std::shared_ptr<const MetaDataInfo> meta_info =
+ std::static_pointer_cast<const MetaDataInfo>(parser_->GetManifestData(
+ app_keys::kTizenMetaDataKey));
+ if (!meta_info)
+ return true;
+
+ for (application_x* app : GListRange<application_x*>(manifest->application)) {
+ app->metadata = GenerateMetadataListX(*meta_info);
+ }
+ return true;
+}
+
+bool StepParse::FillAccounts(manifest_x* manifest) {
+ std::shared_ptr<const AccountInfo> account_info =
+ std::static_pointer_cast<const AccountInfo>(parser_->GetManifestData(
+ app_keys::kAccountKey));
+ if (!account_info)
+ return true;
+ common_installer::AccountInfo info;
+ for (auto& account : account_info->accounts()) {
+ common_installer::SingleAccountInfo single_info;
+ single_info.capabilities = account.capabilities;
+ single_info.icon_paths = account.icon_paths;
+ single_info.multiple_account_support = account.multiple_account_support;
+ single_info.names = account.names;
+ // wgt can contain only one app so this assumes mainapp_id is valid here
+ single_info.appid = manifest->mainapp_id;
+ info.set_account(single_info);
+ }
+ context_->manifest_plugins_data.get().account_info.set(info);
+ return true;
+}
+
+bool StepParse::FillExtraManifestInfo(manifest_x* manifest) {
+ return FillAccounts(manifest);
+}
+
+bool StepParse::FillManifestX(manifest_x* manifest) {
+ if (!FillIconPaths(manifest))
+ return false;
+ if (!FillUIApplicationInfo(manifest))
+ return false;
+ if (!FillWidgetInfo(manifest))
+ return false;
+ if (!FillInstallationInfo(manifest))
+ return false;
+ if (!FillPrivileges(manifest))
+ return false;
+ if (!FillAppControl(manifest))
+ return false;
+ if (!FillCategories(manifest))
+ return false;
+ if (!FillMetadata(manifest))
+ return false;
+ // TODO(t.iwanek): fix adding ui application element
+ // for now adding application service is added here because rest of code
+ // assumes that there is one application at manifest->application
+ // so this must execute last
+ if (!FillServiceApplicationInfo(manifest))
+ return false;
+ if (!FillBackgroundCategoryInfo(manifest))
+ return false;
+ if (!FillExtraManifestInfo(manifest))
+ return false;
+ return true;
+}
+
+bool StepParse::LocateConfigFile() {
+ return StepParse::Check(context_->unpacked_dir_path.get());
+}
+
+common_installer::Step::Status StepParse::process() {
+ if (!LocateConfigFile()) {
+ LOG(ERROR) << "No config.xml";
+ return common_installer::Step::Status::ERROR;
+ }
+
+ parser_.reset(new wgt::parse::WidgetConfigParser());
+ if (!parser_->ParseManifest(config_)) {
+ LOG(ERROR) << "[Parse] Parse failed. " << parser_->GetErrorMessage();
+ return common_installer::Step::Status::ERROR;
+ }
+ if (check_start_file_) {
+ if (!parser_->HasValidStartFile()) {
+ LOG(ERROR) << parser_->GetErrorMessage();
+ return common_installer::Step::Status::ERROR;
+ }
+ if (!parser_->HasValidServicesStartFiles()) {
+ LOG(ERROR) << parser_->GetErrorMessage();
+ return common_installer::Step::Status::ERROR;
+ }
+ }
+
+ manifest_x* manifest =
+ static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
+ if (!FillManifestX(manifest)) {
+ LOG(ERROR) << "[Parse] Storing manifest_x failed. "
+ << parser_->GetErrorMessage();
+ return common_installer::Step::Status::ERROR;
+ }
+
+ // Copy data from ManifestData to InstallerContext
+ std::shared_ptr<const TizenApplicationInfo> info =
+ std::static_pointer_cast<const TizenApplicationInfo>(
+ parser_->GetManifestData(
+ wgt::application_widget_keys::kTizenApplicationKey));
+ std::shared_ptr<const WidgetInfo> wgt_info =
+ std::static_pointer_cast<const WidgetInfo>(
+ parser_->GetManifestData(
+ wgt::application_widget_keys::kTizenWidgetKey));
+
+ std::string name;
+ const auto& name_set = wgt_info->name_set();
+ if (name_set.find("") != name_set.end())
+ name = name_set.find("")->second;
+ if (name_set.begin() != name_set.end())
+ name = name_set.begin()->second;
+
+ std::string short_name;
+ const auto& short_name_set = wgt_info->short_name_set();
+ if (short_name_set.find("") != short_name_set.end())
+ short_name = short_name_set.find("")->second;
+ if (short_name_set.begin() != short_name_set.end())
+ short_name = short_name_set.begin()->second;
+
+ const std::string& package_version = wgt_info->version();
+ const std::string& required_api_version = info->required_version();
+
+ manifest->api_version = strdup(required_api_version.c_str());
+ context_->pkgid.set(manifest->package);
+
+ // write pkgid for recovery file
+ if (context_->recovery_info.get().recovery_file) {
+ context_->recovery_info.get().recovery_file->set_pkgid(manifest->package);
+ context_->recovery_info.get().recovery_file->WriteAndCommitFileContent();
+ }
+
+ std::shared_ptr<const PermissionsInfo> perm_info =
+ std::static_pointer_cast<const PermissionsInfo>(
+ parser_->GetManifestData(
+ wgt::application_widget_keys::kTizenPermissionsKey));
+ parser::PermissionSet permissions;
+ if (perm_info)
+ permissions = perm_info->GetAPIPermissions();
+
+ std::unique_ptr<WgtBackendData> backend_data(new WgtBackendData());
+
+ std::shared_ptr<const SettingInfo> settings_info =
+ std::static_pointer_cast<const SettingInfo>(
+ parser_->GetManifestData(
+ wgt::application_widget_keys::kTizenSettingKey));
+ if (settings_info)
+ backend_data->settings.set(*settings_info);
+
+ context_->backend_data.set(backend_data.release());
+
+ LOG(DEBUG) << " Read data -[ ";
+ LOG(DEBUG) << "App id: " << info->id();
+ LOG(DEBUG) << " package = " << info->package();
+ LOG(DEBUG) << " id = " << info->id();
+ LOG(DEBUG) << " name = " << name;
+ LOG(DEBUG) << " short_name = " << short_name;
+ LOG(DEBUG) << " aplication version = " << package_version;
+ LOG(DEBUG) << " api_version = " << info->required_version();
+ LOG(DEBUG) << " launch_mode = " << info->launch_mode();
+ LOG(DEBUG) << " privileges -[";
+ for (const auto& p : permissions) {
+ LOG(DEBUG) << " " << p;
+ }
+ LOG(DEBUG) << " ]-";
+ LOG(DEBUG) << "]-";
+
+ context_->manifest_data.set(manifest);
+ return common_installer::Step::Status::OK;
+}
+
+bool StepParse::Check(const boost::filesystem::path& widget_path) {
+ boost::filesystem::path config = widget_path;
+ config /= "config.xml";
+
+ LOG(DEBUG) << "config.xml path: " << config;
+
+ if (!boost::filesystem::exists(config))
+ return false;
+
+ config_ = config;
+ return true;
+}
+
+} // namespace parse
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_PARSE_H_
+#define WGT_STEP_STEP_PARSE_H_
+
+#include <boost/filesystem.hpp>
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+#include <manifest_handlers/permissions_handler.h>
+#include <manifest_handlers/widget_config_parser.h>
+#include <manifest_parser/utils/logging.h>
+
+#include <memory>
+#include <set>
+#include <string>
+
+namespace wgt {
+namespace parse {
+
+/**
+ * \brief This step parse manifest.xml document
+ */
+class StepParse : public common_installer::Step {
+ public:
+ /**
+ * \brief Explicit constructor
+ *
+ * \param context Installer context
+ * \param check_start_file Flag if start file should be validated
+ */
+ explicit StepParse(common_installer::InstallerContext* context,
+ bool check_start_file);
+
+ /**
+ * \brief
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ protected:
+ virtual bool LocateConfigFile();
+ bool Check(const boost::filesystem::path& widget_path);
+
+ boost::filesystem::path config_;
+
+ private:
+ std::set<std::string> ExtractPrivileges(
+ std::shared_ptr<const PermissionsInfo> perm_info) const;
+
+ const std::string& GetPackageVersion(const std::string& manifest_version);
+
+ bool FillInstallationInfo(manifest_x* manifest);
+ bool FillIconPaths(manifest_x* manifest);
+ bool FillWidgetInfo(manifest_x* manifest);
+ bool FillUIApplicationInfo(manifest_x* manifest);
+ bool FillServiceApplicationInfo(manifest_x* manifest);
+ bool FillAppControl(manifest_x* manifest);
+ bool FillPrivileges(manifest_x* manifest);
+ bool FillCategories(manifest_x* manifest);
+ bool FillMetadata(manifest_x* manifest);
+ bool FillExtraManifestInfo(manifest_x* manifest);
+ bool FillAccounts(manifest_x* manifest);
+ bool FillBackgroundCategoryInfo(manifest_x* manifest);
+ bool FillManifestX(manifest_x* manifest);
+
+ std::unique_ptr<wgt::parse::WidgetConfigParser> parser_;
+ bool check_start_file_;
+
+ SCOPE_LOG_TAG(Parse)
+};
+
+} // namespace parse
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_PARSE_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_parse_recovery.h"
+
+#include <common/backup_paths.h>
+#include <common/installer_context.h>
+
+namespace {
+
+const char kResWgtPath[] = "res/wgt";
+
+}
+
+namespace wgt {
+namespace parse {
+
+StepParseRecovery::StepParseRecovery(
+ common_installer::InstallerContext* context)
+ : StepParse(context, false) {
+}
+
+common_installer::Step::Status StepParseRecovery::process() {
+ (void) StepParse::process();
+ return Status::OK;
+}
+
+common_installer::Step::Status StepParseRecovery::precheck() {
+ if (context_->root_application_path.get().empty()) {
+ LOG(ERROR) << "Root path of packages in not set";
+ return Status::ERROR;
+ }
+ if (context_->pkgid.get().empty()) {
+ LOG(WARNING) << "Pkgid is not set. Parsing skipped";
+ return Status::OK;
+ }
+ return Status::OK;
+}
+
+bool StepParseRecovery::LocateConfigFile() {
+ context_->pkg_path.set(
+ context_->root_application_path.get() / context_->pkgid.get());
+
+ if (Check(common_installer::GetBackupPathForPackagePath(
+ context_->pkg_path.get()) / kResWgtPath))
+ return true;
+
+ if (Check(context_->pkg_path.get() / kResWgtPath))
+ return true;
+
+ return false;
+}
+
+} // namespace parse
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_PARSE_RECOVERY_H_
+#define WGT_STEP_STEP_PARSE_RECOVERY_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "wgt/step/step_parse.h"
+
+namespace wgt {
+namespace parse {
+/**
+ * \brief The StepParseRecovery class
+ * Retrievies package information from config.xml during RECOVERY.
+ *
+ * Step is used in recovery mode.
+ *
+ * Parse config.xml file by guessing possible locations:
+ * - backup package directory
+ * - package installation directory
+ * to get information about widget package to be recovered.
+ *
+ */
+class StepParseRecovery : public StepParse {
+ public:
+ /**
+ * \brief Explicit constructor
+ *
+ * \param context installer context
+ */
+ explicit StepParseRecovery(common_installer::InstallerContext* context);
+
+ /**
+ * \brief Parse config.xml
+ *
+ * \return Status::OK
+ */
+ Status process() override;
+
+ /**
+ * \brief Validate requirements for this step
+ *
+ * \return Status::ERROR when root path of packages is missing,
+ * Status::OK otherwise
+ */
+ Status precheck() override;
+
+ /**
+ * \brief Locate config.xml file
+ *
+ * \return true if config.xml is found
+ */
+ bool LocateConfigFile() override;
+
+ SCOPE_LOG_TAG(ParseRecovery)
+};
+
+} // namespace parse
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_PARSE_RECOVERY_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_rds_modify.h"
+
+#include <boost/system/error_code.hpp>
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/utils/file_util.h>
+
+namespace wgt {
+namespace rds {
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace cu = common_installer;
+
+StepRDSModify::StepRDSModify(common_installer::InstallerContext* context)
+ : Step(context),
+ backend_data_(nullptr) {}
+
+common_installer::Step::Status StepRDSModify::precheck() {
+ if (context_->unpacked_dir_path.get().empty()) {
+ LOG(ERROR) << "unpacked dir path is not set";
+ return common_installer::Step::Status::ERROR;
+ }
+ if (!bf::exists(context_->unpacked_dir_path.get())) {
+ LOG(ERROR) << "unpacked_dir_path ("
+ << context_->unpacked_dir_path.get()
+ << ") path does not exist";
+ return common_installer::Step::Status::ERROR;
+ }
+ if (context_->pkgid.get().empty()) {
+ LOG(ERROR) << "pkgid is not set";
+ return common_installer::Step::Status::ERROR;
+ }
+ if (!context_->manifest_data.get()) {
+ LOG(ERROR) << "no manifest info available";
+ return common_installer::Step::Status::ERROR;
+ }
+ // TODO(w.kosowicz): check if config of installed app was encrypted
+ backend_data_ = static_cast<WgtBackendData*>(context_->backend_data.get());
+ if (!backend_data_) {
+ LOG(ERROR) << "no backend data";
+ return common_installer::Step::Status::ERROR;
+ }
+ return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepRDSModify::process() {
+ LOG(INFO) << "entered process of step modify";
+ if (!SetUpTempBackupDir()) {
+ LOG(ERROR) << "unable to setup temp directory";
+ return common_installer::Step::Status::ERROR;
+ }
+ context_->pkg_path.set(
+ context_->root_application_path.get() /context_->pkgid.get());
+ bf::path install_path = context_->pkg_path.get() / "res" / "wgt";
+ bf::path unzip_path = context_->unpacked_dir_path.get();
+ if (!AddFiles(unzip_path, install_path) ||
+ !ModifyFiles(unzip_path, install_path) ||
+ !DeleteFiles(install_path)) {
+ LOG(ERROR) << "error during file operation";
+ return common_installer::Step::Status::ERROR;
+ }
+ return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepRDSModify::undo() {
+ RestoreFiles();
+ return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepRDSModify::clean() {
+ if (bf::exists(backup_temp_dir_))
+ bf::remove_all(backup_temp_dir_);
+ return common_installer::Step::Status::OK;
+}
+
+bool StepRDSModify::AddFiles(bf::path unzip_path, bf::path install_path) {
+ LOG(INFO) << "about to add files";
+ bs::error_code error;
+ for (const auto& file : backend_data_->files_to_add.get()) {
+ if (!PerformBackup(file, Operation::ADD)) {
+ LOG(ERROR) << "unable to perform backup of added file";
+ return false;
+ }
+ bf::path temp_install_path(install_path / file);
+ if (bf::is_directory(temp_install_path)) {
+ if (!bf::exists(temp_install_path) &&
+ (!cu::CreateDir(temp_install_path))) {
+ LOG(ERROR) << "unable to create dir for temp backup data";
+ return false;
+ }
+ } else {
+ if (!bf::exists(temp_install_path.parent_path()) &&
+ !cu::CreateDir(temp_install_path.parent_path())) {
+ LOG(ERROR) << "unable to create dir for temp backup data";
+ return false;
+ }
+ bf::path temp_unzip_path(unzip_path / file);
+ bf::copy_file(temp_unzip_path, temp_install_path, error);
+ if (error) {
+ LOG(ERROR) << "unable to add file " << error.message();
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool StepRDSModify::ModifyFiles(bf::path unzip_path, bf::path install_path) {
+ LOG(INFO) << "about to modify files";
+ bs::error_code error;
+ for (const auto& file : backend_data_->files_to_modify.get()) {
+ bf::path temp_install_path(install_path / file);
+ bf::path temp_unzip_path(unzip_path / file);
+ if (!PerformBackup(file, Operation::MODIFY)) {
+ LOG(ERROR) << "unable to perform backup of to be modified file";
+ return false;
+ }
+ bf::copy_file(temp_unzip_path, temp_install_path,
+ bf::copy_option::overwrite_if_exists, error);
+ if (error) {
+ LOG(ERROR) << "unable to modify file " << error.message();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool StepRDSModify::DeleteFiles(bf::path install_path) {
+ LOG(INFO) << "about to delete files";
+ bs::error_code error;
+ for (const auto& file : backend_data_->files_to_delete.get()) {
+ if (!PerformBackup(file, Operation::DELETE)) {
+ LOG(ERROR) << "unable to perform backup of to be deleted file";
+ return false;
+ }
+ bf::remove(install_path / file, error);
+ if (error) {
+ LOG(ERROR) <<"unable to delete files " << error.message();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool StepRDSModify::SetUpTempBackupDir() {
+ LOG(INFO) << "about to setup tmp backup dir";
+ bs::error_code error;
+ backup_temp_dir_ = "/tmp/" /
+ bf::unique_path("%%%%-%%%%-%%%%-%%%%", error);
+ if (error || !cu::CreateDir(backup_temp_dir_)) {
+ LOG(ERROR) << "unable to create backup data temp dir";
+ return false;
+ }
+
+ return true;
+}
+
+bool StepRDSModify::PerformBackup(std::string relative_path,
+ Operation operation) {
+ if (backup_temp_dir_.empty())
+ return false;
+ if (operation == Operation::DELETE || operation == Operation::MODIFY) {
+ bf::path app_path = context_->pkg_path.get() / "res" / "wgt";
+ bf::path source_path = app_path / relative_path;
+ if (bf::is_directory(source_path)) {
+ if (!cu::CreateDir(backup_temp_dir_ / relative_path)) {
+ LOG(ERROR) << "unable to create dir for temp backup data";
+ return false;
+ }
+ } else {
+ bs::error_code error;
+ bf::path tmp_dest_path = backup_temp_dir_ / relative_path;
+ if (!bf::exists((tmp_dest_path).parent_path()) &&
+ (!cu::CreateDir((tmp_dest_path).parent_path()))) {
+ LOG(ERROR) << "unable to create dir for temp backup data";
+ return false;
+ }
+ bf::copy_file(source_path, tmp_dest_path, error);
+ if (error) {
+ LOG(ERROR) << "unable to backup file: "
+ << source_path << " : " << error.message();
+ return false;
+ }
+ }
+ }
+ success_modifications_.push_back(std::make_pair(relative_path, operation));
+ return true;
+}
+
+void StepRDSModify::RestoreFiles() {
+ LOG(ERROR) << "error occured about to restore files";
+ bf::path app_path(context_->pkg_path.get());
+ for (std::pair<std::string, Operation>& modification :
+ success_modifications_) {
+ bf::path source_path(backup_temp_dir_ / modification.first);
+ bf::path destination_path(app_path / modification.first);
+ if (modification.second == Operation::ADD) {
+ if (bf::is_directory(source_path)) {
+ bf::remove_all(destination_path);
+ } else {
+ bf::remove(destination_path);
+ }
+ } else if (modification.second == Operation::MODIFY) {
+ bf::copy_file(source_path, destination_path,
+ bf::copy_option::overwrite_if_exists);
+ } else {
+ if (bf::is_directory(source_path)) {
+ cu::CreateDir(destination_path);
+ } else {
+ bf::copy_file(source_path, destination_path,
+ bf::copy_option::overwrite_if_exists);
+ }
+ }
+ }
+ // after files are restore delete temporary location
+ bf::remove_all(backup_temp_dir_);
+}
+
+} // namespace rds
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_RDS_MODIFY_H_
+#define WGT_STEP_STEP_RDS_MODIFY_H_
+
+#include <boost/filesystem.hpp>
+#include <common/step/step.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "wgt/wgt_backend_data.h"
+
+namespace wgt {
+namespace rds {
+
+/**
+ * \brief Step that apply RDS modification during reinstallation process
+ */
+class StepRDSModify : public common_installer::Step {
+ public:
+ /**
+ * \brief Explicit constructor
+ *
+ * \param context Installer context
+ */
+ explicit StepRDSModify(common_installer::InstallerContext* context);
+
+ /**
+ * \brief
+ *
+ * \return
+ */
+ Status process() override;
+
+ /**
+ * \brief Remove files from temporary location
+ *
+ * \return Status::OK
+ */
+ Status clean() override;
+
+ /**
+ * \brief Restore files to the state from before RDS installation
+ *
+ * \return Status::OK
+ */
+ Status undo() override;
+
+ /**
+ * \brief
+ *
+ * \return Status::ERROR when manifest is missing, pkgid is missing,
+ * or when path to the unpacked directory is missing or not exist,
+ * Status::OK otherwise
+ */
+ Status precheck() override;
+
+ private:
+ enum class Operation {
+ ADD,
+ MODIFY,
+ DELETE
+ };
+
+ bool AddFiles(boost::filesystem::path unzip_path,
+ boost::filesystem::path install_path);
+ bool ModifyFiles(boost::filesystem::path unzip_path,
+ boost::filesystem::path install_path);
+ bool DeleteFiles(boost::filesystem::path install_path);
+ bool SetUpTempBackupDir();
+ void DeleteTempBackupDir();
+ bool PerformBackup(std::string relative_path, Operation operation);
+ void RestoreFiles();
+
+ WgtBackendData* backend_data_;
+ std::vector<std::pair<std::string, Operation>> success_modifications_;
+ boost::filesystem::path backup_temp_dir_;
+ std::vector<std::string> files_to_modify_;
+ std::vector<std::string> files_to_add_;
+ std::vector<std::string> files_to_delete_;
+};
+} // namespace rds
+} // namespace wgt
+#endif // WGT_STEP_STEP_RDS_MODIFY_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_rds_parse.h"
+
+#include <manifest_parser/utils/logging.h>
+
+#include <memory>
+
+#include "wgt/rds_parser.h"
+#include "wgt/wgt_backend_data.h"
+
+
+namespace wgt {
+namespace rds {
+
+namespace bf = boost::filesystem;
+
+common_installer::Step::Status StepRDSParse::precheck() {
+ bf::path rdsPath(context_->unpacked_dir_path.get() / ".rds_delta");
+ if (!bf::exists(rdsPath)) {
+ LOG(ERROR) << "no rds_delta file";
+ return common_installer::Step::Status::ERROR;
+ }
+ rds_file_path_ = rdsPath;
+ return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepRDSParse::process() {
+ wgt::rds_parser::RDSParser parser(rds_file_path_.native());
+ if (!parser.Parse()) {
+ LOG(ERROR) << "parsing of rds delta failed";
+ return common_installer::Step::Status::ERROR;
+ }
+
+ WgtBackendData* backend_data =
+ static_cast<WgtBackendData*>(context_->backend_data.get());
+ if (!backend_data) {
+ LOG(ERROR) << "no wgt backend data available";
+ return common_installer::Step::Status::ERROR;
+ }
+ backend_data->files_to_modify.set(parser.files_to_modify());
+ backend_data->files_to_add.set(parser.files_to_add());
+ backend_data->files_to_delete.set(parser.files_to_delete());
+ return common_installer::Step::Status::OK;
+}
+
+} // namespace rds
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_RDS_PARSE_H_
+#define WGT_STEP_STEP_RDS_PARSE_H_
+
+#include <common/step/step.h>
+
+#include <boost/filesystem.hpp>
+#include <string>
+#include <vector>
+
+namespace wgt {
+namespace rds {
+
+/**
+ * \brief This step parse .rds_delta file
+ *
+ * This is to prepare RDS installation process
+ */
+class StepRDSParse : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Parse .rds_delta file
+ *
+ * \return Status::ERROR when wgt backend data are missing,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Validate if .rds_delta file exist
+ *
+ * \return Status::Error if file not exist,
+ * Status::OK otherwise
+ */
+ Status precheck() override;
+
+ private:
+ boost::filesystem::path rds_file_path_;
+};
+} // namespace rds
+} // namespace wgt
+#endif // WGT_STEP_STEP_RDS_PARSE_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_remove_encryption_data.h"
+
+#include <web_app_enc.h>
+
+#include <manifest_parser/utils/logging.h>
+
+namespace wgt {
+namespace encrypt {
+
+common_installer::Step::Status StepRemoveEncryptionData::clean() {
+ wae_app_type_e enc_type =
+ context_->request_mode.get() == common_installer::RequestMode::GLOBAL ?
+ WAE_DOWNLOADED_GLOBAL_APP : WAE_DOWNLOADED_NORMAL_APP;
+
+ // There is no check, if application was encrypted or not
+ // (it is not saved anywhere in tizen manifest)
+ // so, if WAE_ERROR_NO_KEY error, then application was not encrypted
+ int ret = wae_remove_app_dek(context_->pkgid.get().c_str(), enc_type);
+ if (WAE_ERROR_NONE == ret || WAE_ERROR_NO_KEY == ret) {
+ LOG(DEBUG) << "Encryption data removed (if existed)";
+ return common_installer::Step::Status::OK;
+ }
+
+ switch (ret) {
+ case WAE_ERROR_INVALID_PARAMETER:
+ LOG(ERROR) << "Error while removing encryption data: "
+ "WAE_ERROR_INVALID_PARAMETER";
+ break;
+ case WAE_ERROR_PERMISSION_DENIED:
+ LOG(ERROR) << "Error while removing encryption data: "
+ "WAE_ERROR_PERMISSION_DENIED";
+ break;
+ case WAE_ERROR_KEY_MANAGER:
+ LOG(ERROR) << "Error while removing encryption data: "
+ "WAE_ERROR_KEY_MANAGER";
+ break;
+ case WAE_ERROR_UNKNOWN:
+ LOG(ERROR) << "Error while removing encryption data: "
+ "WAE_ERROR_UNKNOWN";
+ break;
+ default:
+ LOG(ERROR) << "Error while removing encryption data: "
+ "UNKNOWN";
+ break;
+ }
+ return common_installer::Step::Status::ERROR;
+}
+
+} // namespace encrypt
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_REMOVE_ENCRYPTION_DATA_H_
+#define WGT_STEP_STEP_REMOVE_ENCRYPTION_DATA_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/step/step.h>
+
+namespace wgt {
+namespace encrypt {
+
+/**
+ * This step remove encryption keys used for encryption during installation
+ *
+ * This step is called during uninstallation process
+ */
+class StepRemoveEncryptionData : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Empty method - the actual work is done in clean() to delay it
+ *
+ * \return Status::OK
+ */
+ Status process() override { return Status::OK; }
+
+ /**
+ * \brief Remove encryption keys from database
+ *
+ * \return Status::ERROR in case of failure,
+ * Status::OK otherwise
+ */
+ Status clean() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ SCOPE_LOG_TAG(RemoveEncryptionData)
+};
+} // namespace encrypt
+} // namespace wgt
+#endif // WGT_STEP_STEP_REMOVE_ENCRYPTION_DATA_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_wgt_copy_storage_directories.h"
+
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+
+#include <common/utils/file_util.h>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+namespace {
+
+const char kDataLocation[] = "data";
+const char kSharedLocation[] = "shared";
+const char kSharedDataLocation[] = "shared/data";
+const char kSharedTrustedLocation[] = "shared/trusted";
+const char kResWgtSubPath[] = "res/wgt";
+const char kTemporaryData[] = "tmp";
+} // namespace
+
+namespace wgt {
+namespace filesystem {
+
+common_installer::Step::Status StepWgtCopyStorageDirectories::process() {
+ Status status = CreatePrivateTmpDir();
+ if (status != Status::OK)
+ return status;
+ if (!CacheDir())
+ return Status::ERROR;
+
+ int version = context_->manifest_data.get()->api_version[0] - '0';
+ if (version < 3) {
+ LOG(DEBUG) << "Shared directory coping for tizen 2.x";
+ return StepCopyStorageDirectories::process();
+ }
+
+ LOG(DEBUG) << "Shared directory coping for tizen 3.x";
+ status = CopySharedDirectory();
+ if (status != Status::OK)
+ return status;
+
+ return CopyDataDirectory();
+}
+
+common_installer::Step::Status StepWgtCopyStorageDirectories::undo() {
+ int version = context_->manifest_data.get()->api_version[0] - '0';
+ if (version < 3) {
+ LOG(DEBUG) << "Shared directory coping for tizen 2.x";
+ return StepCopyStorageDirectories::undo();
+ }
+
+ UndoSharedDirectory();
+ UndoDataDirectory();
+ return Status::OK;
+}
+
+void StepWgtCopyStorageDirectories::UndoSharedDirectory() {
+ if (!MoveAppStorage(context_->pkg_path.get(),
+ backup_path_,
+ kSharedDataLocation)) {
+ LOG(ERROR) <<
+ "Failed to undo moving of shared/data directory for widget in update";
+ }
+
+ if (!MoveAppStorage(context_->pkg_path.get(),
+ backup_path_,
+ kSharedTrustedLocation)) {
+ LOG(ERROR) << "Failed to undo moving of shared/trusted directory"
+ << "for widget in update";
+ }
+}
+
+void StepWgtCopyStorageDirectories::UndoDataDirectory() {
+ if (!MoveAppStorage(context_->pkg_path.get(),
+ backup_path_,
+ kDataLocation)) {
+ LOG(ERROR)
+ << "Failed to undo moving of private directory for widget in update";
+ }
+}
+
+common_installer::Step::Status
+StepWgtCopyStorageDirectories::HandleWgtSharedDirectory() {
+ bf::path res_wgt_path = context_->pkg_path.get() / kResWgtSubPath;
+ bf::path shared_source = res_wgt_path / kSharedLocation;
+ bf::path shared_destination = context_->pkg_path.get() / kSharedLocation;
+
+ // Move shared if exist in wgt
+ if (bf::exists(shared_source)) {
+ if (!common_installer::MoveDir(shared_source, shared_destination)) {
+ LOG(ERROR) << "Failed to move shared data from res/wgt to shared";
+ return Status::ERROR;
+ }
+ }
+
+ // Create shared directory if not present yet
+ if (!bf::exists(shared_destination)) {
+ bs::error_code error_code;
+ bf::create_directory(shared_destination, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create shared storage directory";
+ return Status::ERROR;
+ }
+ }
+
+ // Symlink created shared directory
+ bs::error_code error_code;
+ bf::create_symlink(shared_destination, shared_source, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create symbolic link for shared dir"
+ << boost::system::system_error(error_code).what();
+ return Status::ERROR;
+ }
+ return Status::OK;
+}
+
+common_installer::Step::Status
+StepWgtCopyStorageDirectories::CopySharedDirectory() {
+ Status status = HandleWgtSharedDirectory();
+ if (status != Status::OK)
+ return status;
+
+ if (!MoveAppStorage(backup_path_,
+ context_->pkg_path.get(),
+ kSharedDataLocation)) {
+ LOG(ERROR) <<
+ "Failed to restore shared/data directory for widget in update";
+ return Status::ERROR;
+ }
+
+ if (!MoveAppStorage(backup_path_,
+ context_->pkg_path.get(),
+ kSharedTrustedLocation)) {
+ LOG(ERROR) <<
+ "Failed to restore shared/trusted directory for widget in update";
+ return Status::ERROR;
+ }
+
+ return Status::OK;
+}
+
+common_installer::Step::Status
+StepWgtCopyStorageDirectories::CopyDataDirectory() {
+ if (!MoveAppStorage(backup_path_,
+ context_->pkg_path.get(),
+ kDataLocation)) {
+ LOG(ERROR) << "Failed to restore private directory for widget in update";
+ return Status::ERROR;
+ }
+ return Status::OK;
+}
+
+common_installer::Step::Status
+StepWgtCopyStorageDirectories::CreatePrivateTmpDir() {
+ bs::error_code error_code;
+ bf::path tmp_path = context_->pkg_path.get() / kTemporaryData;
+ bf::create_directory(tmp_path, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create private temporary directory for package";
+ return Status::ERROR;
+ }
+ return Status::OK;
+}
+
+} // namespace filesystem
+} // namespace wgt
+
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_WGT_COPY_STORAGE_DIRECTORIES_H_
+#define WGT_STEP_STEP_WGT_COPY_STORAGE_DIRECTORIES_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/step/step_copy_storage_directories.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief Update installation (WGT).
+ * Responsible for coping shared and data directories.
+ * It extends StepCopyStorageDirectories (it adds distinction between
+ * 2.x and 3.x shared dir handling
+ */
+class StepWgtCopyStorageDirectories
+ : public common_installer::filesystem::StepCopyStorageDirectories {
+ public:
+ using StepCopyStorageDirectories::StepCopyStorageDirectories;
+
+ /**
+ * \brief Create shared and private directories,
+ * and copy/restore widget files to appropriate directory
+ *
+ * \return Status::ERROR when failed to create temporary location,
+ * private temporary location, or failed to restore
+ * shared/private directory for widget,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Move files from shared/private directories back to source directory
+ *
+ * \return Status::OK
+ */
+ Status undo() override;
+
+ private:
+ Status CopySharedDirectory();
+ Status CopyDataDirectory();
+ Status HandleWgtSharedDirectory();
+ void UndoSharedDirectory();
+ void UndoDataDirectory();
+ Status CreatePrivateTmpDir();
+
+ SCOPE_LOG_TAG(CopyWgtStorageDirectories)
+};
+
+} // namespace filesystem
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_WGT_COPY_STORAGE_DIRECTORIES_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_wgt_create_icons.h"
+
+namespace {
+
+const char kResWgt[] = "res/wgt";
+
+}
+
+namespace wgt {
+namespace filesystem {
+
+boost::filesystem::path StepWgtCreateIcons::GetIconRoot() const {
+ return context_->pkg_path.get() / kResWgt;
+}
+
+} // namespace filesystem
+} // namespace wgt
+
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_WGT_CREATE_ICONS_H_
+#define WGT_STEP_STEP_WGT_CREATE_ICONS_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/step/step_create_icons.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief This step return path to widget icon
+ */
+class StepWgtCreateIcons
+ : public common_installer::filesystem::StepCreateIcons {
+ public:
+ using StepCreateIcons::StepCreateIcons;
+
+ /**
+ * \brief Return path to widget icon
+ *
+ * \return path to widget icon
+ */
+ boost::filesystem::path GetIconRoot() const override;
+
+ SCOPE_LOG_TAG(WgtCreateIcons)
+};
+
+} // namespace filesystem
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_WGT_CREATE_ICONS_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_wgt_create_storage_directories.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/utils/file_util.h>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+namespace {
+
+const char kSharedLocation[] = "shared";
+const char kResWgtSubPath[] = "res/wgt";
+const char kTemporaryData[] = "tmp";
+
+} // namespace
+
+namespace wgt {
+namespace filesystem {
+
+common_installer::Step::Status StepWgtCreateStorageDirectories::process() {
+ if (!PrivateDir())
+ return Status::ERROR;
+
+ char version = context_->manifest_data.get()->api_version[0];
+
+ if ((version-'0') < 3) {
+ LOG(DEBUG) << "Shared directory preparation for tizen 2.x";
+ if (!ShareDir())
+ return Status::ERROR;
+ } else {
+ LOG(DEBUG) << "Shared directory preparation for tizen 3.x";
+ if (!ShareDirFor3x())
+ return Status::ERROR;
+ }
+
+ if (!SubShareDir())
+ return Status::ERROR;
+
+ if (!CreatePrivateTmpDir())
+ return Status::ERROR;
+
+ if (!CacheDir())
+ return Status::ERROR;
+
+ return Status::OK;
+}
+
+bool StepWgtCreateStorageDirectories::ShareDirFor2x() {
+ bs::error_code error_code;
+ bf::path shared_path = context_->pkg_path.get() / kSharedLocation;
+ bf::create_directory(shared_path, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create shared directory for widget";
+ return false;
+ }
+ return true;
+}
+
+bool StepWgtCreateStorageDirectories::ShareDirFor3x() {
+ bf::path res_wgt_path = context_->pkg_path.get() / kResWgtSubPath;
+ if (!bf::exists(res_wgt_path / kSharedLocation)) {
+ if (!ShareDir())
+ return false;
+ } else {
+ bf::path src = res_wgt_path / kSharedLocation;
+ bf::path dst = context_->pkg_path.get() / kSharedLocation;
+ if (!common_installer::MoveDir(src, dst)) {
+ LOG(ERROR) << "Failed to move shared data from res/wgt to shared";
+ return false;
+ }
+
+ bs::error_code error_code;
+ bf::create_symlink(dst, src, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create symbolic link for shared dir"
+ << boost::system::system_error(error_code).what();
+ return false;
+ }
+ } // else
+ return true;
+}
+
+bool StepWgtCreateStorageDirectories::CreatePrivateTmpDir() {
+ bs::error_code error_code;
+ bf::path tmp_path = context_->pkg_path.get() / kTemporaryData;
+ bf::create_directory(tmp_path, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create private temporary directory for package";
+ return false;
+ }
+ return true;
+}
+
+} // namespace filesystem
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_WGT_CREATE_STORAGE_DIRECTORIES_H_
+#define WGT_STEP_STEP_WGT_CREATE_STORAGE_DIRECTORIES_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/step/step_create_storage_directories.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief Installation (WGT).
+ * Responsible for creating shared and data directories.
+ * It extends StepCreateStorageDirectories (it adds distinction between
+ * 2.x and 3.x shared dir handling
+ *
+ * process method implements creation of shared and data directories.
+ * Depending on tizen required version it can also move "shared" resources
+ * from ./res/wgt/shared to ./shared dir (and create symlink back
+ * to ./res/wgt/shared).
+ *
+ * StepWgtCreateStorageDirectories works on following directory:
+ * * TZ_SYS_RW/PKGID (/usr/apps/PKGID)
+ * * TZ_SER_APPS/PKGID (/{HOME}/apps_rw/PKGID)
+ */
+class StepWgtCreateStorageDirectories :
+ public common_installer::filesystem::StepCreateStorageDirectories {
+ public:
+ using StepCreateStorageDirectories::StepCreateStorageDirectories;
+
+ /**
+ * \brief Create shared and private directories
+ *
+ * \return Status::ERROR when failed to create temporary location, or
+ * private temporary location
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ private:
+ bool ShareDirFor2x();
+ bool ShareDirFor3x();
+
+ bool CreatePrivateTmpDir();
+
+ SCOPE_LOG_TAG(CreateWgtStorageDirectories)
+};
+
+} // namespace filesystem
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_WGT_CREATE_STORAGE_DIRECTORIES_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_wgt_resource_directory.h"
+
+#include <boost/filesystem/path.hpp>
+
+#include <common/utils/file_util.h>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+namespace wgt {
+namespace filesystem {
+
+common_installer::Step::Status StepWgtResourceDirectory::process() {
+ bf::path temp_path = context_->unpacked_dir_path.get();
+ temp_path += ".temp";
+ bf::path resource_path = context_->unpacked_dir_path.get() / "res/wgt";
+
+ if (!common_installer::MoveDir(context_->unpacked_dir_path.get(),
+ temp_path)) {
+ LOG(ERROR) << "Failed to move: " << context_->unpacked_dir_path.get()
+ << " to: " << temp_path;
+ return Status::ERROR;
+ }
+ bs::error_code error;
+ bf::create_directories(resource_path.parent_path(), error);
+ if (error) {
+ LOG(ERROR) << "Failed to create proper directory structure in widget";
+ return Status::ERROR;
+ }
+ if (!common_installer::MoveDir(temp_path, resource_path)) {
+ LOG(ERROR) << "Failed to move: " << temp_path << " to: " << resource_path;
+ return Status::ERROR;
+ }
+
+ LOG(INFO) << "Widget content moved to res/wgt subdirectory";
+ return Status::OK;
+}
+
+} // namespace filesystem
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_WGT_RESOURCE_DIRECTORY_H_
+#define WGT_STEP_STEP_WGT_RESOURCE_DIRECTORY_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <common/app_installer.h>
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief This step fixes unpacked directory structure so that all widget
+ * content is moved from root path to res/wgt before we copy whole directory in
+ * StepCopy
+ */
+class StepWgtResourceDirectory : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ /**
+ * \brief Create directory structure and copy content of widget package
+ *
+ * \return Status::ERROR when failed to create proper directory structure or
+ * move source directory to destination directory,
+ * Status::OK otherwise
+ */
+ Status process() override;
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status clean() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status undo() override { return Status::OK; }
+
+ /**
+ * \brief Empty method
+ *
+ * \return Status::OK
+ */
+ Status precheck() override { return Status::OK; }
+
+ SCOPE_LOG_TAG(CreateWgtResourceDirectory)
+};
+
+} // namespace filesystem
+} // namespace wgt
+
+#endif // WGT_STEP_STEP_WGT_RESOURCE_DIRECTORY_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/wgt_app_query_interface.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/pkgmgr_registration.h>
+#include <common/request.h>
+#include <common/utils/file_util.h>
+
+#include <manifest_handlers/application_manifest_constants.h>
+#include <manifest_handlers/tizen_application_handler.h>
+#include <manifest_handlers/widget_handler.h>
+#include <manifest_parser/manifest_parser.h>
+#include <manifest_parser/utils/logging.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+
+namespace {
+
+std::string GetInstallationPackagePath(int argc, char** argv) {
+ std::string path;
+ for (int i = 0; i < argc; ++i) {
+ if (!strcmp(argv[i], "-i")) {
+ if (i + 1 < argc) {
+ path = argv[i + 1];
+ break;
+ }
+ }
+ }
+ return path;
+}
+
+std::string GetPkgIdFromPath(const std::string& path) {
+ bf::path tmp_path = common_installer::GenerateTmpDir("/tmp");
+ bs::error_code code;
+ bf::create_directories(tmp_path, code);
+ if (code)
+ return {};
+ if (!common_installer::ExtractToTmpDir(path.c_str(), tmp_path,
+ "config.xml")) {
+ bf::remove_all(tmp_path, code);
+ return {};
+ }
+ bf::path config_path = tmp_path / "config.xml";
+ std::vector<parser::ManifestHandler*> handlers = {
+ new wgt::parse::WidgetHandler(),
+ new wgt::parse::TizenApplicationHandler()
+ };
+ std::unique_ptr<parser::ManifestHandlerRegistry> registry(
+ new parser::ManifestHandlerRegistry(handlers));
+ std::unique_ptr<parser::ManifestParser> parser(
+ new parser::ManifestParser(std::move(registry)));
+ if (!parser->ParseManifest(config_path)) {
+ bf::remove_all(tmp_path, code);
+ return {};
+ }
+ auto info = std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
+ parser->GetManifestData(
+ wgt::application_widget_keys::kTizenApplicationKey));
+ if (!info) {
+ bf::remove_all(tmp_path, code);
+ return {};
+ }
+ std::string pkg_id = info->package();
+
+ bf::remove_all(tmp_path, code);
+ return pkg_id;
+}
+
+} // namespace
+
+namespace wgt {
+
+bool WgtAppQueryInterface::IsAppInstalledByArgv(int argc, char** argv) {
+ std::string path = GetInstallationPackagePath(argc, argv);
+ if (path.empty()) {
+ // not the installaton
+ return false;
+ }
+ std::string pkg_id = GetPkgIdFromPath(path);
+ if (pkg_id.empty())
+ return false;
+ return ci::IsPackageInstalled(pkg_id, ci::GetRequestMode());
+}
+
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_WGT_APP_QUERY_INTERFACE_H_
+#define WGT_WGT_APP_QUERY_INTERFACE_H_
+
+#include <common/app_query_interface.h>
+
+namespace wgt {
+
+/**
+ * \brief Helper functionalities used before
+ * configuring app-installer steps.
+ * Eg. it is used to check, if package is to be installed or updated
+ */
+class WgtAppQueryInterface : public common_installer::AppQueryInterface {
+ public:
+ /**
+ * \brief method for checking if package is installed based
+ * on argv
+ *
+ * \param argc main() argc argument passed to the backend
+ * \param argv main() argv argument passed to the backend
+ *
+ * \return true if package is installed
+ */
+ bool IsAppInstalledByArgv(int argc, char** argv) override;
+};
+
+} // namespace wgt
+
+#endif // WGT_WGT_APP_QUERY_INTERFACE_H_
--- /dev/null
+/* 2014, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <common/pkgmgr_interface.h>
+#include <cerrno>
+
+#include "wgt/wgt_app_query_interface.h"
+#include "wgt/wgt_installer.h"
+
+namespace ci = common_installer;
+
+int main(int argc, char** argv) {
+ wgt::WgtAppQueryInterface query_interface;
+ auto pkgmgr = ci::PkgMgrInterface::Create(argc, argv, &query_interface);
+ if (!pkgmgr) {
+ LOG(ERROR) << "Options of pkgmgr installer cannot be parsed";
+ return EINVAL;
+ }
+ wgt::WgtInstaller installer(pkgmgr);
+ return (installer.Run() == ci::AppInstaller::Result::OK) ? 0 : 1;
+}
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_WGT_BACKEND_DATA_H_
+#define WGT_WGT_BACKEND_DATA_H_
+
+#include <common/installer_context.h>
+#include <common/utils/property.h>
+
+#include <manifest_handlers/setting_handler.h>
+
+#include <string>
+#include <vector>
+
+namespace wgt {
+
+/**
+ * \brief Class that is used within specific backends to keep additional
+ * information regarding package
+ */
+class WgtBackendData : public common_installer::BackendData {
+ public:
+ /**
+ * \brief Property of vector of files to add
+ */
+ Property<std::vector<std::string>> files_to_add;
+
+ /**
+ * \brief Property of vector of files to modify
+ */
+ Property<std::vector<std::string>> files_to_modify;
+
+ /**
+ * \brief Property of vector of files to delete
+ */
+ Property<std::vector<std::string>> files_to_delete;
+
+ /**
+ * \brief Property of SettingInfo
+ */
+ Property<parse::SettingInfo> settings;
+};
+
+} // namespace wgt
+
+#endif // WGT_WGT_BACKEND_DATA_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/wgt_installer.h"
+
+#include <manifest_handlers/widget_config_parser.h>
+
+#include <common/pkgmgr_interface.h>
+#include <common/step/step_configure.h>
+#include <common/step/step_backup_manifest.h>
+#include <common/step/step_backup_icons.h>
+#include <common/step/step_copy.h>
+#include <common/step/step_copy_backup.h>
+#include <common/step/step_copy_storage_directories.h>
+#include <common/step/step_delta_patch.h>
+#include <common/step/step_fail.h>
+#include <common/step/step_kill_apps.h>
+#include <common/step/step_open_recovery_file.h>
+#include <common/step/step_parse.h>
+#include <common/step/step_privilege_compatibility.h>
+#include <common/step/step_register_app.h>
+#include <common/step/step_recover_application.h>
+#include <common/step/step_recover_files.h>
+#include <common/step/step_recover_icons.h>
+#include <common/step/step_recover_manifest.h>
+#include <common/step/step_recover_security.h>
+#include <common/step/step_recover_storage_directories.h>
+#include <common/step/step_remove_icons.h>
+#include <common/step/step_remove_files.h>
+#include <common/step/step_remove_temporary_directory.h>
+#include <common/step/step_revoke_security.h>
+#include <common/step/step_register_security.h>
+#include <common/step/step_rollback_deinstallation_security.h>
+#include <common/step/step_rollback_installation_security.h>
+#include <common/step/step_old_manifest.h>
+#include <common/step/step_check_signature.h>
+#include <common/step/step_unregister_app.h>
+#include <common/step/step_unzip.h>
+#include <common/step/step_update_app.h>
+#include <common/step/step_update_security.h>
+#include <common/step/step_check_old_certificate.h>
+
+#include "wgt/step/step_add_default_privileges.h"
+#include "wgt/step/step_check_settings_level.h"
+#include "wgt/step/step_check_wgt_background_category.h"
+#include "wgt/step/step_create_symbolic_link.h"
+#include "wgt/step/step_encrypt_resources.h"
+#include "wgt/step/step_generate_xml.h"
+#include "wgt/step/step_parse.h"
+#include "wgt/step/step_parse_recovery.h"
+#include "wgt/step/step_rds_modify.h"
+#include "wgt/step/step_rds_parse.h"
+#include "wgt/step/step_remove_encryption_data.h"
+#include "wgt/step/step_wgt_copy_storage_directories.h"
+#include "wgt/step/step_wgt_create_icons.h"
+#include "wgt/step/step_wgt_create_storage_directories.h"
+#include "wgt/step/step_wgt_resource_directory.h"
+
+namespace ci = common_installer;
+
+namespace wgt {
+
+WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr)
+ : AppInstaller("wgt", pkgrmgr) {
+ /* treat the request */
+ switch (pkgmgr_->GetRequestType()) {
+ case ci::RequestType::Install : {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::filesystem::StepUnzip>();
+ AddStep<wgt::parse::StepParse>(true);
+ AddStep<ci::security::StepCheckSignature>();
+ AddStep<ci::security::StepPrivilegeCompatibility>();
+ AddStep<wgt::security::StepCheckSettingsLevel>();
+ AddStep<wgt::security::StepCheckWgtBackgroundCategory>();
+ AddStep<wgt::encrypt::StepEncryptResources>();
+ AddStep<wgt::filesystem::StepWgtResourceDirectory>();
+ AddStep<ci::security::StepRollbackInstallationSecurity>();
+ AddStep<ci::filesystem::StepCopy>();
+ AddStep<wgt::filesystem::StepWgtCreateStorageDirectories>();
+ AddStep<wgt::filesystem::StepCreateSymbolicLink>();
+ AddStep<wgt::filesystem::StepWgtCreateIcons>();
+ AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<ci::pkgmgr::StepRegisterApplication>();
+ AddStep<ci::security::StepRegisterSecurity>();
+ break;
+ }
+ case ci::RequestType::Update: {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::filesystem::StepUnzip>();
+ AddStep<wgt::parse::StepParse>(true);
+ AddStep<ci::security::StepCheckSignature>();
+ AddStep<ci::security::StepPrivilegeCompatibility>();
+ AddStep<wgt::security::StepCheckSettingsLevel>();
+ AddStep<wgt::security::StepCheckWgtBackgroundCategory>();
+ AddStep<ci::security::StepCheckOldCertificate>();
+ AddStep<wgt::filesystem::StepWgtResourceDirectory>();
+ AddStep<ci::backup::StepOldManifest>();
+ AddStep<ci::pkgmgr::StepKillApps>();
+ AddStep<ci::backup::StepBackupManifest>();
+ AddStep<ci::backup::StepBackupIcons>();
+ AddStep<ci::backup::StepCopyBackup>();
+ AddStep<wgt::filesystem::StepWgtCopyStorageDirectories>();
+ AddStep<wgt::filesystem::StepCreateSymbolicLink>();
+ AddStep<wgt::filesystem::StepWgtCreateIcons>();
+ AddStep<ci::security::StepUpdateSecurity>();
+ AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<ci::pkgmgr::StepUpdateApplication>();
+ break;
+ }
+ case ci::RequestType::Uninstall: {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::parse::StepParse>();
+ AddStep<ci::pkgmgr::StepKillApps>();
+ AddStep<ci::backup::StepBackupManifest>();
+ AddStep<ci::pkgmgr::StepUnregisterApplication>();
+ AddStep<ci::security::StepRollbackDeinstallationSecurity>();
+ AddStep<ci::filesystem::StepRemoveFiles>();
+ AddStep<ci::filesystem::StepRemoveIcons>();
+ AddStep<wgt::encrypt::StepRemoveEncryptionData>();
+ AddStep<ci::security::StepRevokeSecurity>();
+ break;
+ }
+ case ci::RequestType::Reinstall: {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<wgt::parse::StepParse>(false);
+ AddStep<ci::pkgmgr::StepKillApps>();
+ AddStep<ci::backup::StepOldManifest>();
+ AddStep<wgt::rds::StepRDSParse>();
+ AddStep<wgt::rds::StepRDSModify>();
+ AddStep<ci::security::StepUpdateSecurity>();
+ break;
+ }
+ case ci::RequestType::Delta: {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::filesystem::StepUnzip>();
+ // TODO(t.iwanek): manifest is parsed twice...
+ AddStep<wgt::parse::StepParse>(false); // start file may not have changed
+ AddStep<ci::filesystem::StepDeltaPatch>("res/wgt/");
+ AddStep<wgt::parse::StepParse>(true);
+ AddStep<ci::security::StepCheckSignature>();
+ AddStep<ci::security::StepPrivilegeCompatibility>();
+ AddStep<wgt::security::StepCheckSettingsLevel>();
+ AddStep<wgt::security::StepCheckWgtBackgroundCategory>();
+ AddStep<ci::security::StepCheckOldCertificate>();
+ AddStep<wgt::filesystem::StepWgtResourceDirectory>();
+ AddStep<ci::backup::StepOldManifest>();
+ AddStep<ci::pkgmgr::StepKillApps>();
+ AddStep<ci::backup::StepBackupManifest>();
+ AddStep<ci::backup::StepBackupIcons>();
+ AddStep<ci::backup::StepCopyBackup>();
+ AddStep<wgt::filesystem::StepWgtCopyStorageDirectories>();
+ AddStep<wgt::filesystem::StepCreateSymbolicLink>();
+ AddStep<wgt::filesystem::StepWgtCreateIcons>();
+ AddStep<ci::security::StepUpdateSecurity>();
+ AddStep<wgt::pkgmgr::StepGenerateXml>();
+ AddStep<ci::pkgmgr::StepUpdateApplication>();
+ break;
+ }
+ case ci::RequestType::Recovery: {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::recovery::StepOpenRecoveryFile>();
+ AddStep<wgt::parse::StepParseRecovery>();
+ AddStep<ci::pkgmgr::StepRecoverApplication>();
+ AddStep<ci::filesystem::StepRemoveTemporaryDirectory>();
+ AddStep<ci::filesystem::StepRecoverIcons>();
+ AddStep<ci::filesystem::StepRecoverManifest>();
+ AddStep<ci::filesystem::StepRecoverStorageDirectories>();
+ AddStep<ci::filesystem::StepRecoverFiles>();
+ AddStep<ci::security::StepRecoverSecurity>();
+ break;
+ }
+ default: {
+ AddStep<ci::configuration::StepFail>();
+ }
+ }
+}
+
+} // namespace wgt
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_WGT_INSTALLER_H_
+#define WGT_WGT_INSTALLER_H_
+
+#include <common/app_installer.h>
+
+namespace wgt {
+
+/**
+ * \brief The WgtInstaller class
+ * Subclass of AppInstaller class dedicated for handling wgt request
+ *
+ * Performs all types of requests of wgt packages and sets required sequence of
+ * steps
+ */
+class WgtInstaller : public common_installer::AppInstaller {
+ public:
+ /**
+ * \brief Explicit constructor
+ *
+ * \param pkgmgr pointer to pkgmgr
+ */
+ explicit WgtInstaller(common_installer::PkgMgrPtr pkgrmgr);
+};
+
+} // namespace wgt
+
+#endif // WGT_WGT_INSTALLER_H_