Move wgt-backend implementation from app-installers 86/54886/2 accepted/tizen/mobile/20151219.044135 accepted/tizen/tv/20151219.044546 accepted/tizen/wearable/20151219.044843 submit/tizen/20151218.151823 submit/tizen_common/20151229.144031 submit/tizen_common/20151229.154718
authorTomasz Iwanek <t.iwanek@samsung.com>
Mon, 14 Dec 2015 12:58:10 +0000 (13:58 +0100)
committerTomasz Iwanek <t.iwanek@samsung.com>
Fri, 18 Dec 2015 11:33:23 +0000 (12:33 +0100)
Requires to be submitted with:
 - https://review.tizen.org/gerrit/#/c/54291/

Aligned with app-installer's commit: 532a4707928d6d137c2cb93ae3523f25f0ac06ee

Change-Id: I30347bd6ca66026d3e363bb16000a44e2d791f39

67 files changed:
CMakeLists.txt [new file with mode: 0644]
cmake/Modules/ApplyPkgConfig.cmake [new file with mode: 0644]
packaging/wgt-backend-tests.manifest [new file with mode: 0644]
packaging/wgt-backend.manifest [new file with mode: 0644]
packaging/wgt-backend.spec
src/CMakeLists.txt [new file with mode: 0644]
src/unit_tests/CMakeLists.txt [new file with mode: 0644]
src/unit_tests/smoke_test.cc [new file with mode: 0644]
src/unit_tests/test_samples/smoke/DeinstallationMode.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/DeinstallationMode_Rollback.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/DeltaMode.delta [new file with mode: 0644]
src/unit_tests/test_samples/smoke/DeltaMode.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/InstallationMode.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/InstallationMode_GoodSignature.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/InstallationMode_Rollback.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/InstallationMode_WrongSignature.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/RDSMode.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/RecoveryMode_ForInstallation.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate_2.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/UpdateMode.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/UpdateMode_2.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/UpdateMode_Rollback.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/UpdateMode_Rollback_2.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/delta_dir/.rds_delta [new file with mode: 0644]
src/unit_tests/test_samples/smoke/delta_dir/ADDED [new file with mode: 0644]
src/unit_tests/test_samples/smoke/delta_dir/MODIFIED [new file with mode: 0644]
src/unit_tests/test_samples/smoke/delta_dir/config.xml [new file with mode: 0644]
src/wgt/CMakeLists.txt [new file with mode: 0644]
src/wgt/rds_parser.cc [new file with mode: 0644]
src/wgt/rds_parser.h [new file with mode: 0644]
src/wgt/step/step_add_default_privileges.cc [new file with mode: 0644]
src/wgt/step/step_add_default_privileges.h [new file with mode: 0644]
src/wgt/step/step_check_settings_level.cc [new file with mode: 0644]
src/wgt/step/step_check_settings_level.h [new file with mode: 0644]
src/wgt/step/step_check_wgt_background_category.cc [new file with mode: 0644]
src/wgt/step/step_check_wgt_background_category.h [new file with mode: 0644]
src/wgt/step/step_create_symbolic_link.cc [new file with mode: 0644]
src/wgt/step/step_create_symbolic_link.h [new file with mode: 0644]
src/wgt/step/step_encrypt_resources.cc [new file with mode: 0644]
src/wgt/step/step_encrypt_resources.h [new file with mode: 0644]
src/wgt/step/step_generate_xml.cc [new file with mode: 0644]
src/wgt/step/step_generate_xml.h [new file with mode: 0644]
src/wgt/step/step_parse.cc [new file with mode: 0644]
src/wgt/step/step_parse.h [new file with mode: 0644]
src/wgt/step/step_parse_recovery.cc [new file with mode: 0644]
src/wgt/step/step_parse_recovery.h [new file with mode: 0644]
src/wgt/step/step_rds_modify.cc [new file with mode: 0644]
src/wgt/step/step_rds_modify.h [new file with mode: 0644]
src/wgt/step/step_rds_parse.cc [new file with mode: 0644]
src/wgt/step/step_rds_parse.h [new file with mode: 0644]
src/wgt/step/step_remove_encryption_data.cc [new file with mode: 0644]
src/wgt/step/step_remove_encryption_data.h [new file with mode: 0644]
src/wgt/step/step_wgt_copy_storage_directories.cc [new file with mode: 0644]
src/wgt/step/step_wgt_copy_storage_directories.h [new file with mode: 0644]
src/wgt/step/step_wgt_create_icons.cc [new file with mode: 0644]
src/wgt/step/step_wgt_create_icons.h [new file with mode: 0644]
src/wgt/step/step_wgt_create_storage_directories.cc [new file with mode: 0644]
src/wgt/step/step_wgt_create_storage_directories.h [new file with mode: 0644]
src/wgt/step/step_wgt_resource_directory.cc [new file with mode: 0644]
src/wgt/step/step_wgt_resource_directory.h [new file with mode: 0644]
src/wgt/wgt_app_query_interface.cc [new file with mode: 0644]
src/wgt/wgt_app_query_interface.h [new file with mode: 0644]
src/wgt/wgt_backend.cc [new file with mode: 0644]
src/wgt/wgt_backend_data.h [new file with mode: 0644]
src/wgt/wgt_installer.cc [new file with mode: 0644]
src/wgt/wgt_installer.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..565d531
--- /dev/null
@@ -0,0 +1,48 @@
+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)
diff --git a/cmake/Modules/ApplyPkgConfig.cmake b/cmake/Modules/ApplyPkgConfig.cmake
new file mode 100644 (file)
index 0000000..97679d7
--- /dev/null
@@ -0,0 +1,35 @@
+# 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)
diff --git a/packaging/wgt-backend-tests.manifest b/packaging/wgt-backend-tests.manifest
new file mode 100644 (file)
index 0000000..6c0eb4f
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+        <request>
+                <domain name="_" />
+        </request>
+        <assign>
+                <filesystem path="/usr/bin/wgt-backend-ut/smoke_test" exec_label="User" />
+        </assign>
+</manifest>
diff --git a/packaging/wgt-backend.manifest b/packaging/wgt-backend.manifest
new file mode 100644 (file)
index 0000000..55125da
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+        <request>
+                <domain name="_" />
+        </request>
+        <assign>
+                <filesystem path="/usr/bin/wgt-backend" exec_label="User" />
+        </assign>
+</manifest>
index 3c17083..9c001e1 100644 (file)
@@ -9,9 +9,59 @@ Group:          Application Framework/Package Management
 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
-
-
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f0e3653
--- /dev/null
@@ -0,0 +1,2 @@
+ADD_SUBDIRECTORY(wgt)
+ADD_SUBDIRECTORY(unit_tests)
diff --git a/src/unit_tests/CMakeLists.txt b/src/unit_tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9c92d11
--- /dev/null
@@ -0,0 +1,22 @@
+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})
diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc
new file mode 100644 (file)
index 0000000..38f8e33
--- /dev/null
@@ -0,0 +1,473 @@
+// 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();
+}
diff --git a/src/unit_tests/test_samples/smoke/DeinstallationMode.wgt b/src/unit_tests/test_samples/smoke/DeinstallationMode.wgt
new file mode 100644 (file)
index 0000000..bf5b7d0
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/DeinstallationMode.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/DeinstallationMode_Rollback.wgt b/src/unit_tests/test_samples/smoke/DeinstallationMode_Rollback.wgt
new file mode 100644 (file)
index 0000000..ea83495
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/DeinstallationMode_Rollback.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/DeltaMode.delta b/src/unit_tests/test_samples/smoke/DeltaMode.delta
new file mode 100644 (file)
index 0000000..2cf6105
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/DeltaMode.delta differ
diff --git a/src/unit_tests/test_samples/smoke/DeltaMode.wgt b/src/unit_tests/test_samples/smoke/DeltaMode.wgt
new file mode 100644 (file)
index 0000000..2837000
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/DeltaMode.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/InstallationMode.wgt b/src/unit_tests/test_samples/smoke/InstallationMode.wgt
new file mode 100644 (file)
index 0000000..8fe0773
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/InstallationMode.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/InstallationMode_GoodSignature.wgt b/src/unit_tests/test_samples/smoke/InstallationMode_GoodSignature.wgt
new file mode 100644 (file)
index 0000000..87604e7
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/InstallationMode_GoodSignature.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/InstallationMode_Rollback.wgt b/src/unit_tests/test_samples/smoke/InstallationMode_Rollback.wgt
new file mode 100644 (file)
index 0000000..4742bbe
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/InstallationMode_Rollback.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/InstallationMode_WrongSignature.wgt b/src/unit_tests/test_samples/smoke/InstallationMode_WrongSignature.wgt
new file mode 100644 (file)
index 0000000..8731bea
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/InstallationMode_WrongSignature.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/RDSMode.wgt b/src/unit_tests/test_samples/smoke/RDSMode.wgt
new file mode 100644 (file)
index 0000000..1245406
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/RDSMode.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/RecoveryMode_ForInstallation.wgt b/src/unit_tests/test_samples/smoke/RecoveryMode_ForInstallation.wgt
new file mode 100644 (file)
index 0000000..1244cf5
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/RecoveryMode_ForInstallation.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate.wgt b/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate.wgt
new file mode 100644 (file)
index 0000000..d1f0b4b
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate_2.wgt b/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate_2.wgt
new file mode 100644 (file)
index 0000000..37d89dd
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/RecoveryMode_ForUpdate_2.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/UpdateMode.wgt b/src/unit_tests/test_samples/smoke/UpdateMode.wgt
new file mode 100644 (file)
index 0000000..1c22e45
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/UpdateMode.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/UpdateMode_2.wgt b/src/unit_tests/test_samples/smoke/UpdateMode_2.wgt
new file mode 100644 (file)
index 0000000..39ab8a8
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/UpdateMode_2.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/UpdateMode_Rollback.wgt b/src/unit_tests/test_samples/smoke/UpdateMode_Rollback.wgt
new file mode 100644 (file)
index 0000000..3e090e4
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/UpdateMode_Rollback.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/UpdateMode_Rollback_2.wgt b/src/unit_tests/test_samples/smoke/UpdateMode_Rollback_2.wgt
new file mode 100644 (file)
index 0000000..20efef2
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/UpdateMode_Rollback_2.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/delta_dir/.rds_delta b/src/unit_tests/test_samples/smoke/delta_dir/.rds_delta
new file mode 100644 (file)
index 0000000..fb08dcc
--- /dev/null
@@ -0,0 +1,6 @@
+#add
+ADDED
+#modify
+MODIFIED
+#delete
+DELETED
diff --git a/src/unit_tests/test_samples/smoke/delta_dir/ADDED b/src/unit_tests/test_samples/smoke/delta_dir/ADDED
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/unit_tests/test_samples/smoke/delta_dir/MODIFIED b/src/unit_tests/test_samples/smoke/delta_dir/MODIFIED
new file mode 100644 (file)
index 0000000..0cfbf08
--- /dev/null
@@ -0,0 +1 @@
+2
diff --git a/src/unit_tests/test_samples/smoke/delta_dir/config.xml b/src/unit_tests/test_samples/smoke/delta_dir/config.xml
new file mode 100644 (file)
index 0000000..66d7bdc
--- /dev/null
@@ -0,0 +1,9 @@
+<?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>
diff --git a/src/wgt/CMakeLists.txt b/src/wgt/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6bd0300
--- /dev/null
@@ -0,0 +1,51 @@
+# 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})
diff --git a/src/wgt/rds_parser.cc b/src/wgt/rds_parser.cc
new file mode 100644 (file)
index 0000000..9f2fbb7
--- /dev/null
@@ -0,0 +1,61 @@
+// 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
diff --git a/src/wgt/rds_parser.h b/src/wgt/rds_parser.h
new file mode 100644 (file)
index 0000000..7c412d1
--- /dev/null
@@ -0,0 +1,63 @@
+// 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_
diff --git a/src/wgt/step/step_add_default_privileges.cc b/src/wgt/step/step_add_default_privileges.cc
new file mode 100644 (file)
index 0000000..18eb902
--- /dev/null
@@ -0,0 +1,38 @@
+// 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
diff --git a/src/wgt/step/step_add_default_privileges.h b/src/wgt/step/step_add_default_privileges.h
new file mode 100644 (file)
index 0000000..928ab84
--- /dev/null
@@ -0,0 +1,59 @@
+// 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_
diff --git a/src/wgt/step/step_check_settings_level.cc b/src/wgt/step/step_check_settings_level.cc
new file mode 100644 (file)
index 0000000..664e376
--- /dev/null
@@ -0,0 +1,47 @@
+// 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
diff --git a/src/wgt/step/step_check_settings_level.h b/src/wgt/step/step_check_settings_level.h
new file mode 100644 (file)
index 0000000..bac5bf2
--- /dev/null
@@ -0,0 +1,59 @@
+// 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_
diff --git a/src/wgt/step/step_check_wgt_background_category.cc b/src/wgt/step/step_check_wgt_background_category.cc
new file mode 100644 (file)
index 0000000..c652fc2
--- /dev/null
@@ -0,0 +1,30 @@
+// 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
diff --git a/src/wgt/step/step_check_wgt_background_category.h b/src/wgt/step/step_check_wgt_background_category.h
new file mode 100644 (file)
index 0000000..33b5b23
--- /dev/null
@@ -0,0 +1,31 @@
+// 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_
diff --git a/src/wgt/step/step_create_symbolic_link.cc b/src/wgt/step/step_create_symbolic_link.cc
new file mode 100644 (file)
index 0000000..1a3eda2
--- /dev/null
@@ -0,0 +1,71 @@
+/* 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
diff --git a/src/wgt/step/step_create_symbolic_link.h b/src/wgt/step/step_create_symbolic_link.h
new file mode 100644 (file)
index 0000000..df51fde
--- /dev/null
@@ -0,0 +1,61 @@
+// 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_
diff --git a/src/wgt/step/step_encrypt_resources.cc b/src/wgt/step/step_encrypt_resources.cc
new file mode 100644 (file)
index 0000000..08f659d
--- /dev/null
@@ -0,0 +1,215 @@
+// 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
diff --git a/src/wgt/step/step_encrypt_resources.h b/src/wgt/step/step_encrypt_resources.h
new file mode 100644 (file)
index 0000000..2d64a51
--- /dev/null
@@ -0,0 +1,66 @@
+// 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_
diff --git a/src/wgt/step/step_generate_xml.cc b/src/wgt/step/step_generate_xml.cc
new file mode 100644 (file)
index 0000000..055fd3f
--- /dev/null
@@ -0,0 +1,494 @@
+/* 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
diff --git a/src/wgt/step/step_generate_xml.h b/src/wgt/step/step_generate_xml.h
new file mode 100644 (file)
index 0000000..5351991
--- /dev/null
@@ -0,0 +1,45 @@
+/* 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_
diff --git a/src/wgt/step/step_parse.cc b/src/wgt/step/step_parse.cc
new file mode 100644 (file)
index 0000000..ac36e10
--- /dev/null
@@ -0,0 +1,574 @@
+/* 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
diff --git a/src/wgt/step/step_parse.h b/src/wgt/step/step_parse.h
new file mode 100644 (file)
index 0000000..115ccf0
--- /dev/null
@@ -0,0 +1,100 @@
+// 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_
diff --git a/src/wgt/step/step_parse_recovery.cc b/src/wgt/step/step_parse_recovery.cc
new file mode 100644 (file)
index 0000000..7fe4a10
--- /dev/null
@@ -0,0 +1,56 @@
+// 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
diff --git a/src/wgt/step/step_parse_recovery.h b/src/wgt/step/step_parse_recovery.h
new file mode 100644 (file)
index 0000000..b5ed147
--- /dev/null
@@ -0,0 +1,63 @@
+// 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_
diff --git a/src/wgt/step/step_rds_modify.cc b/src/wgt/step/step_rds_modify.cc
new file mode 100644 (file)
index 0000000..41b9bc1
--- /dev/null
@@ -0,0 +1,226 @@
+// 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
diff --git a/src/wgt/step/step_rds_modify.h b/src/wgt/step/step_rds_modify.h
new file mode 100644 (file)
index 0000000..4f0a289
--- /dev/null
@@ -0,0 +1,87 @@
+// 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_
diff --git a/src/wgt/step/step_rds_parse.cc b/src/wgt/step/step_rds_parse.cc
new file mode 100644 (file)
index 0000000..b98900e
--- /dev/null
@@ -0,0 +1,50 @@
+// 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
diff --git a/src/wgt/step/step_rds_parse.h b/src/wgt/step/step_rds_parse.h
new file mode 100644 (file)
index 0000000..5aea60e
--- /dev/null
@@ -0,0 +1,61 @@
+// 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_
diff --git a/src/wgt/step/step_remove_encryption_data.cc b/src/wgt/step/step_remove_encryption_data.cc
new file mode 100644 (file)
index 0000000..452f32b
--- /dev/null
@@ -0,0 +1,54 @@
+// 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
diff --git a/src/wgt/step/step_remove_encryption_data.h b/src/wgt/step/step_remove_encryption_data.h
new file mode 100644 (file)
index 0000000..291b92e
--- /dev/null
@@ -0,0 +1,57 @@
+// 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_
diff --git a/src/wgt/step/step_wgt_copy_storage_directories.cc b/src/wgt/step/step_wgt_copy_storage_directories.cc
new file mode 100644 (file)
index 0000000..c1929c7
--- /dev/null
@@ -0,0 +1,172 @@
+// 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
+
diff --git a/src/wgt/step/step_wgt_copy_storage_directories.h b/src/wgt/step/step_wgt_copy_storage_directories.h
new file mode 100644 (file)
index 0000000..18eac47
--- /dev/null
@@ -0,0 +1,58 @@
+// 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_
diff --git a/src/wgt/step/step_wgt_create_icons.cc b/src/wgt/step/step_wgt_create_icons.cc
new file mode 100644 (file)
index 0000000..f62588c
--- /dev/null
@@ -0,0 +1,22 @@
+// 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
+
diff --git a/src/wgt/step/step_wgt_create_icons.h b/src/wgt/step/step_wgt_create_icons.h
new file mode 100644 (file)
index 0000000..46c3a8c
--- /dev/null
@@ -0,0 +1,36 @@
+// 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_
diff --git a/src/wgt/step/step_wgt_create_storage_directories.cc b/src/wgt/step/step_wgt_create_storage_directories.cc
new file mode 100644 (file)
index 0000000..708cd12
--- /dev/null
@@ -0,0 +1,102 @@
+// 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
diff --git a/src/wgt/step/step_wgt_create_storage_directories.h b/src/wgt/step/step_wgt_create_storage_directories.h
new file mode 100644 (file)
index 0000000..789c5ee
--- /dev/null
@@ -0,0 +1,77 @@
+// 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_
diff --git a/src/wgt/step/step_wgt_resource_directory.cc b/src/wgt/step/step_wgt_resource_directory.cc
new file mode 100644 (file)
index 0000000..190051f
--- /dev/null
@@ -0,0 +1,44 @@
+// 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
diff --git a/src/wgt/step/step_wgt_resource_directory.h b/src/wgt/step/step_wgt_resource_directory.h
new file mode 100644 (file)
index 0000000..60717ec
--- /dev/null
@@ -0,0 +1,62 @@
+// 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_
diff --git a/src/wgt/wgt_app_query_interface.cc b/src/wgt/wgt_app_query_interface.cc
new file mode 100644 (file)
index 0000000..2a8e046
--- /dev/null
@@ -0,0 +1,101 @@
+// 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
diff --git a/src/wgt/wgt_app_query_interface.h b/src/wgt/wgt_app_query_interface.h
new file mode 100644 (file)
index 0000000..40a9a07
--- /dev/null
@@ -0,0 +1,33 @@
+// 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_
diff --git a/src/wgt/wgt_backend.cc b/src/wgt/wgt_backend.cc
new file mode 100644 (file)
index 0000000..576e861
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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;
+}
diff --git a/src/wgt/wgt_backend_data.h b/src/wgt/wgt_backend_data.h
new file mode 100644 (file)
index 0000000..e3c281b
--- /dev/null
@@ -0,0 +1,47 @@
+// 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_
diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc
new file mode 100644 (file)
index 0000000..9d494b9
--- /dev/null
@@ -0,0 +1,179 @@
+// 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
diff --git a/src/wgt/wgt_installer.h b/src/wgt/wgt_installer.h
new file mode 100644 (file)
index 0000000..7a06a31
--- /dev/null
@@ -0,0 +1,31 @@
+// 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_