From 9ac55ac7e97070792d902ac9682f1767689f07f5 Mon Sep 17 00:00:00 2001 From: Tomasz Iwanek Date: Thu, 21 Jan 2016 13:47:23 +0100 Subject: [PATCH] StepParseManifest StepParseManifest will replace: - common::StepOldManifest - common::StepParse - tpk::StepParse (most of code comes from here) as tpk-manifest-parser needs to be used instead of pkgmgr-parser in parsing manifest file in deinstallation and update modes of tpk-backend as well as wgt-backend. Change-Id: Ib05249c229d1a73d4c79ed5ebeedf72e783dad78 --- CMakeLists.txt | 1 + packaging/app-installers.spec | 1 + src/common/CMakeLists.txt | 2 + src/common/step/step_parse_manifest.cc | 692 +++++++++++++++++++++++++++++++++ src/common/step/step_parse_manifest.h | 102 +++++ 5 files changed, 798 insertions(+) create mode 100644 src/common/step/step_parse_manifest.cc create mode 100644 src/common/step/step_parse_manifest.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e86a679..62bea53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info) PKG_CHECK_MODULES(LIBXML_DEPS REQUIRED libxml-2.0) PKG_CHECK_MODULES(PRIVILEGE_CHECKER_DEPS REQUIRED capi-security-privilege-manager) PKG_CHECK_MODULES(APPMANAGER_DEPS REQUIRED capi-appfw-app-manager) +PKG_CHECK_MODULES(TPK_MANIFEST_HANDLERS_DEPS REQUIRED tpk-manifest-handlers) FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem regex program_options) FIND_PACKAGE(GTest REQUIRED) diff --git a/packaging/app-installers.spec b/packaging/app-installers.spec index 662bfd6..59aa38b 100644 --- a/packaging/app-installers.spec +++ b/packaging/app-installers.spec @@ -31,6 +31,7 @@ BuildRequires: pkgconfig(manifest-parser-utils) BuildRequires: pkgconfig(delta-manifest-handlers) BuildRequires: pkgconfig(capi-security-privilege-manager) BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(tpk-manifest-handlers) Requires: ca-certificates-tizen Requires: libtzplatform-config diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 55e1e15..eae3ded 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -25,6 +25,7 @@ SET(SRCS step/step_delta_patch.cc step/step_fail.cc step/step_kill_apps.cc + step/step_parse_manifest.cc step/step_recover_application.cc step/step_recover_files.cc step/step_recover_icons.cc @@ -71,6 +72,7 @@ APPLY_PKG_CONFIG(${TARGET_LIBNAME_COMMON} PUBLIC PRIVILEGE_CHECKER_DEPS APPMANAGER_DEPS DELTA_MANIFEST_HANDLERS_DEPS + TPK_MANIFEST_HANDLERS_DEPS Boost ) diff --git a/src/common/step/step_parse_manifest.cc b/src/common/step/step_parse_manifest.cc new file mode 100644 index 0000000..e540714 --- /dev/null +++ b/src/common/step/step_parse_manifest.cc @@ -0,0 +1,692 @@ +// 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 "common/step/step_parse_manifest.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/app_installer.h" +#include "common/backup_paths.h" +#include "common/installer_context.h" +#include "common/step/step.h" +#include "common/utils/glist_range.h" + +namespace app_keys = tpk::application_keys; +namespace bf = boost::filesystem; + +namespace { + +const char kManifestFileName[] = "tizen-manifest.xml"; + +} // namepsace + +namespace common_installer { +namespace parse { + +StepParseManifest::StepParseManifest( + InstallerContext* context, ManifestLocation manifest_location, + StoreLocation store_location) + : Step(context), + manifest_location_(manifest_location), + store_location_(store_location) { +} + +Step::Status StepParseManifest::precheck() { + switch (manifest_location_) { + case ManifestLocation::RECOVERY: + case ManifestLocation::INSTALLED: + if (context_->pkgid.get().empty()) { + LOG(ERROR) << "Package id is not set"; + return Status::INVALID_VALUE; + } + break; + case ManifestLocation::PACKAGE: + if (context_->unpacked_dir_path.get().empty()) { + LOG(ERROR) << "Unpacked directory doesn't exist"; + return Status::INVALID_VALUE; + } + break; + default: + LOG(ERROR) << "Unknown manifest location"; + return Status::INVALID_VALUE; + } + return Status::OK; +} + +bool StepParseManifest::LocateConfigFile() { + boost::filesystem::path manifest; + switch (manifest_location_) { + case ManifestLocation::RECOVERY: { + context_->pkg_path.set( + context_->root_application_path.get() / context_->pkgid.get()); + bf::path backup_path = common_installer::GetBackupPathForPackagePath( + context_->pkg_path.get()) / kManifestFileName; + bf::path in_package_path = context_->pkg_path.get() / kManifestFileName; + if (bf::exists(backup_path)) + manifest = backup_path; + else if (bf::exists(in_package_path)) + manifest = in_package_path; + break; + } + case ManifestLocation::INSTALLED: { + bf::path xml_path = bf::path(getUserManifestPath(context_->uid.get())) + / bf::path(context_->pkgid.get()); + xml_path += ".xml"; + context_->xml_path.set(xml_path); + manifest = context_->xml_path.get(); + break; + } + case ManifestLocation::PACKAGE: { + manifest = context_->unpacked_dir_path.get(); + manifest /= kManifestFileName; + break; + } + default: { + LOG(ERROR) << "Unknown manifest location value"; + return false; + } + } + + LOG(DEBUG) << "manifest path: " << manifest; + + if (!boost::filesystem::exists(manifest)) + return false; + + path_ = manifest; + return true; +} + +bool StepParseManifest::FillInstallationInfo(manifest_x* manifest) { + manifest->root_path = strdup( + (context_->root_application_path.get() / manifest->package).c_str()); + manifest->installed_time = + strdup(std::to_string(std::chrono::system_clock::to_time_t( + std::chrono::system_clock::now())).c_str()); + return true; +} + +bool StepParseManifest::FillPackageInfo(manifest_x* manifest) { + std::shared_ptr pkg_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kManifestKey)); + if (!pkg_info) { + LOG(ERROR) << "Package info manifest data has not been found."; + return false; + } + + auto ui_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kUIApplicationKey)); + auto service_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kServiceApplicationKey)); + auto widget_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kWidgetApplicationKey)); + + // mandatory check + if (!ui_application_list && !service_application_list && + !widget_application_list) { + LOG(ERROR) << "UI Application or Service Application or Widget Application " + "are mandatory and has not been found."; + return false; + } + + manifest->ns = strdup(pkg_info->xmlns().c_str()); + manifest->package = strdup(pkg_info->package().c_str()); + manifest->nodisplay_setting = strdup(pkg_info->nodisplay_setting().c_str()); + manifest->appsetting = strdup("false"); + manifest->support_disable = strdup("false"); + manifest->version = strdup(pkg_info->version().c_str()); + manifest->installlocation = strdup(pkg_info->install_location().c_str()); + manifest->api_version = strdup(pkg_info->api_version().c_str()); + if (context_->pkg_type.get().compare("rpm") == 0) + manifest->type = strdup("rpm"); + else + manifest->type = strdup("tpk"); + + for (auto& pair : pkg_info->labels()) { + label_x* label = reinterpret_cast(calloc(1, sizeof(label_x))); + if (!pair.first.empty()) + label->lang = strdup(pair.first.c_str()); + else + label->lang = strdup(DEFAULT_LOCALE); + label->name = strdup(pair.second.c_str()); + manifest->label = g_list_append(manifest->label, label); + } + + std::shared_ptr profile_info = + std::static_pointer_cast( + parser_->GetManifestData(tpk::parse::ProfileInfo::Key())); + if (profile_info) { + for (auto& profile : profile_info->profiles()) { + manifest->deviceprofile = g_list_append(manifest->deviceprofile, + strdup(profile.c_str())); + } + } + + if (ui_application_list) { + manifest->mainapp_id = + strdup(ui_application_list->items[0].app_info.appid().c_str()); + } else if (service_application_list) { + manifest->mainapp_id = + strdup(service_application_list->items[0].app_info.appid().c_str()); + } else if (widget_application_list) { + manifest->mainapp_id = + strdup(widget_application_list->items[0].app_info.appid().c_str()); + } + return true; +} + +bool StepParseManifest::FillAuthorInfo(manifest_x* manifest) { + std::shared_ptr author_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kAuthorKey)); + + if (!author_info) { + LOG(ERROR) << "Author data has not been found."; + return false; + } + + author_x* author = reinterpret_cast(calloc(1, sizeof(author_x))); + author->text = strdup(author_info->name().c_str()); + author->email = strdup(author_info->email().c_str()); + author->href = strdup(author_info->href().c_str()); + author->lang = strdup(DEFAULT_LOCALE); + manifest->author = g_list_append(manifest->author, author); + return true; +} + +bool StepParseManifest::FillDescription(manifest_x* manifest) { + std::shared_ptr description_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kDescriptionKey)); + + if (!description_info) { + LOG(ERROR) << "Description data has not been found."; + return false; + } + + description_x* description = reinterpret_cast + (calloc(1, sizeof(description_x))); + description->text = strdup(description_info->description().c_str()); + description->lang = !description_info->xml_lang().empty() ? + strdup(description_info->xml_lang().c_str()) : strdup(DEFAULT_LOCALE); + manifest->description = g_list_append(manifest->description, description); + return true; +} + +bool StepParseManifest::FillPrivileges(manifest_x* manifest) { + std::shared_ptr perm_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kPrivilegesKey)); + if (!perm_info) + return true; + + std::set privileges = perm_info->GetPrivileges(); + for (auto& priv : privileges) { + manifest->privileges = g_list_append(manifest->privileges, + strdup(priv.c_str())); + } + return true; +} + +bool StepParseManifest::FillWidgetApplication(manifest_x* manifest) { + auto widget_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kWidgetApplicationKey)); + if (!widget_application_list) + return true; + + for (const auto& application : widget_application_list->items) { + // if there is no app yet, set this app as mainapp + bool main_app = manifest->application == nullptr; + + application_x* widget_app = + static_cast(calloc(1, sizeof(application_x))); + widget_app->appid = strdup(application.app_info.appid().c_str()); + widget_app->launch_mode = + strdup(application.app_info.launch_mode().c_str()); + widget_app->multiple = strdup(application.app_info.multiple().c_str()); + widget_app->nodisplay = + strdup(application.app_info.nodisplay().c_str()); + widget_app->type = strdup("capp"); + widget_app->component_type = strdup("widgetapp"); + widget_app->hwacceleration = + strdup(application.app_info.hwacceleration().c_str()); + widget_app->onboot = strdup("false"); + widget_app->autorestart = strdup("false"); + widget_app->mainapp = main_app ? strdup("true") : strdup("false"); + widget_app->enabled = strdup("true"); + widget_app->screenreader = strdup("use-system-setting"); + widget_app->recentimage = strdup("false"); + widget_app->launchcondition = strdup("false"); + widget_app->guestmode_visibility = strdup("true"); + widget_app->permission_type = strdup("normal"); + widget_app->ambient_support = strdup("false"); + widget_app->package = strdup(manifest->package); + widget_app->support_disable = strdup(manifest->support_disable); + manifest->application = g_list_append(manifest->application, widget_app); + if (strncmp(context_->pkg_type.get().c_str(), "rpm", strlen("rpm")) == 0) + widget_app->exec = strdup(application.app_info.exec().c_str()); + else + widget_app->exec = strdup((context_->root_application_path.get() + / manifest->package / "bin" + / application.app_info.exec()).c_str()); + + if (!FillApplicationIconPaths(widget_app, application.app_icons)) + return false; + if (!FillLabel(widget_app, application.label)) + return false; + if (!FillImage(widget_app, application.app_images)) + return false; + if (!FillMetadata(widget_app, application.meta_data)) + return false; + } + return true; +} + +bool StepParseManifest::FillServiceApplication(manifest_x* manifest) { + auto service_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kServiceApplicationKey)); + if (!service_application_list) + return true; + + for (const auto& application : service_application_list->items) { + // if there is no app yet, set this app as mainapp + bool main_app = manifest->application == nullptr; + + application_x* service_app = + static_cast(calloc(1, sizeof(application_x))); + service_app->appid = strdup(application.app_info.appid().c_str()); + service_app->autorestart = + strdup(application.app_info.auto_restart().c_str()); + service_app->onboot = strdup(application.app_info.on_boot().c_str()); + service_app->type = strdup(application.app_info.type().c_str()); + service_app->process_pool = + strdup(application.app_info.process_pool().c_str()); + service_app->component_type = strdup("svcapp"); + service_app->mainapp = main_app ? strdup("true") : strdup("false"); + service_app->enabled = strdup("true"); + service_app->hwacceleration = strdup("default"); + service_app->screenreader = strdup("use-system-setting"); + service_app->recentimage = strdup("false"); + service_app->launchcondition = strdup("false"); + service_app->indicatordisplay = strdup("true"); + service_app->effectimage_type = strdup("image"); + service_app->guestmode_visibility = strdup("true"); + service_app->permission_type = strdup("normal"); + service_app->submode = strdup("false"); + service_app->process_pool = strdup("false"); + service_app->ambient_support = strdup("false"); + service_app->package = strdup(manifest->package); + service_app->support_disable = strdup(manifest->support_disable); + manifest->application = g_list_append(manifest->application, service_app); + if (strncmp(context_->pkg_type.get().c_str(), "rpm", strlen("rpm")) == 0) + service_app->exec = strdup(application.app_info.exec().c_str()); + else + service_app->exec = strdup((context_->root_application_path.get() + / manifest->package / "bin" + / application.app_info.exec()).c_str()); + + if (!FillAppControl(service_app, application.app_control)) + return false; + if (!FillDataControl(service_app, application.data_control)) + return false; + if (!FillApplicationIconPaths(service_app, application.app_icons)) + return false; + if (!FillLabel(service_app, application.label)) + return false; + if (!FillMetadata(service_app, application.meta_data)) + return false; + if (!FillBackgroundCategoryInfo(service_app, + application.background_category)) + return false; + } + return true; +} + +bool StepParseManifest::FillUIApplication(manifest_x* manifest) { + std::shared_ptr ui_application_list = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kUIApplicationKey)); + if (!ui_application_list) + return true; + + for (const auto& application : ui_application_list->items) { + // if there is no app yet, set this app as mainapp + bool main_app = manifest->application == nullptr; + + application_x* ui_app = + static_cast(calloc(1, sizeof(application_x))); + ui_app->appid = strdup(application.app_info.appid().c_str()); + ui_app->launch_mode = strdup(application.app_info.launch_mode().c_str()); + ui_app->multiple = strdup(application.app_info.multiple().c_str()); + ui_app->nodisplay = strdup(application.app_info.nodisplay().c_str()); + ui_app->taskmanage = strdup(application.app_info.taskmanage().c_str()); + ui_app->type = strdup(application.app_info.type().c_str()); + ui_app->component_type = strdup("uiapp"); + ui_app->ui_gadget = strdup(application.app_info.uigadget().c_str()); + ui_app->process_pool = strdup(application.app_info.process_pool().c_str()); + ui_app->submode = strdup(application.app_info.submode().c_str()); + ui_app->indicatordisplay = + strdup(application.app_info.indicator_display().c_str()); + ui_app->effectimage_type = + strdup(application.app_info.effectimage_type().c_str()); + ui_app->portraitimg = + strdup(application.app_info.portrait_image().c_str()); + ui_app->landscapeimg = + strdup(application.app_info.landscape_image().c_str()); + ui_app->submode_mainid = + strdup(application.app_info.submode_mainid().c_str()); + ui_app->hwacceleration = + strdup(application.app_info.hwacceleration().c_str()); + ui_app->onboot = strdup("false"); + ui_app->autorestart = strdup("false"); + ui_app->component_type = strdup("uiapp"); + ui_app->mainapp = main_app ? strdup("true") : strdup("false"); + ui_app->enabled = strdup("true"); + ui_app->screenreader = strdup("use-system-setting"); + ui_app->recentimage = strdup("false"); + ui_app->launchcondition = strdup("false"); + ui_app->guestmode_visibility = strdup("true"); + ui_app->permission_type = strdup("normal"); + ui_app->ambient_support = strdup("false"); + ui_app->package = strdup(manifest->package); + ui_app->support_disable = strdup(manifest->support_disable); + manifest->application = g_list_append(manifest->application, ui_app); + if (strncmp(context_->pkg_type.get().c_str(), "rpm", strlen("rpm")) == 0) + ui_app->exec = strdup(application.app_info.exec().c_str()); + else + ui_app->exec = strdup((context_->root_application_path.get() + / manifest->package / "bin" + / application.app_info.exec()).c_str()); + + + if (!FillAppControl(ui_app, application.app_control)) + return false; + if (!FillDataControl(ui_app, application.data_control)) + return false; + if (!FillApplicationIconPaths(ui_app, application.app_icons)) + return false; + if (!FillLabel(ui_app, application.label)) + return false; + if (!FillImage(ui_app, application.app_images)) + return false; + if (!FillMetadata(ui_app, application.meta_data)) + return false; + if (!FillBackgroundCategoryInfo(ui_app, application.background_category)) + return false; + } + return true; +} + +template +bool StepParseManifest::FillAppControl(application_x* app, + const T& app_control_list) { + if (app_control_list.empty()) + return true; + + for (const auto& control : app_control_list) { + appcontrol_x* app_control = + static_cast(calloc(1, sizeof(appcontrol_x))); + app_control->operation = strdup(control.operation().c_str()); + if (!control.mime().empty()) + app_control->mime = strdup(control.mime().c_str()); + if (!control.uri().empty()) + app_control->uri = strdup(control.uri().c_str()); + app->appcontrol = g_list_append(app->appcontrol, app_control); + } + return true; +} + +template +bool StepParseManifest::FillDataControl(application_x* app, + const T& data_control_list) { + if (data_control_list.empty()) + return true; + + for (const auto& control : data_control_list) { + datacontrol_x* data_control = + static_cast(calloc(1, sizeof(datacontrol_x))); + data_control->access = strdup(control.access().c_str()); + data_control->providerid = strdup(control.providerid().c_str()); + data_control->type = strdup(control.type().c_str()); + app->datacontrol = g_list_append(app->datacontrol, data_control); + } + return true; +} + +template +bool StepParseManifest::FillApplicationIconPaths(application_x* app, + const T& icons_info) { + for (auto& application_icon : icons_info.icons()) { + icon_x* icon = reinterpret_cast (calloc(1, sizeof(icon_x))); + // NOTE: name is an attribute, but the xml writer uses it as text. + // This must be fixed in whole app-installer modules, including wgt. + // Current implementation is just for compatibility. + bf::path text = context_->root_application_path.get() + / context_->pkgid.get() / "shared" / "res" / application_icon.path(); + icon->text = strdup(text.c_str()); + icon->name = strdup(application_icon.path().c_str()); + icon->lang = strdup(DEFAULT_LOCALE); + app->icon = g_list_append(app->icon, icon); + } + return true; +} + +template +bool StepParseManifest::FillLabel(application_x* app, const T& label_list) { + if (label_list.empty()) + return true; + + for (const auto& control : label_list) { + label_x* label = + static_cast(calloc(1, sizeof(label_x))); + // NOTE: name is an attribute, but the xml writer uses it as text. + // This must be fixed in whole app-installer modules, including wgt. + // Current implementation is just for compatibility. + label->text = strdup(control.text().c_str()); + label->name = strdup(control.name().c_str()); + label->lang = !control.xml_lang().empty() ? + strdup(control.xml_lang().c_str()) : strdup(DEFAULT_LOCALE); + app->label = g_list_append(app->label, label); + } + return true; +} + +template +bool StepParseManifest::FillMetadata(application_x* app, + const T& meta_data_list) { + if (meta_data_list.empty()) + return true; + + for (auto& meta : meta_data_list) { + metadata_x* metadata = + static_cast(calloc(1, sizeof(metadata_x))); + metadata->key = strdup(meta.key().c_str()); + metadata->value = strdup(meta.val().c_str()); + app->metadata = g_list_append(app->metadata, metadata); + } + return true; +} + +bool StepParseManifest::FillImage(application_x* app, + const tpk::parse::ApplicationImagesInfo& image_list) { + for (auto& app_image : image_list.images) { + image_x* image = + static_cast(calloc(1, sizeof(image_x))); + image->name = strdup(app_image.name().c_str()); + const std::string& lang = app_image.lang(); + if (!lang.empty()) + image->lang = strdup(lang.c_str()); + else + image->lang = strdup(DEFAULT_LOCALE); + if (!app_image.section().empty()) + image->section = strdup(app_image.section().c_str()); + app->image = g_list_append(app->image, image); + } + return true; +} + +bool StepParseManifest::FillAccounts() { + std::shared_ptr account_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kAccountKey)); + if (!account_info) + return true; + + AccountInfo info; + for (auto& account : account_info->accounts()) { + 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.labels; + // appid has the same value as package + single_info.appid = account.app_id; + single_info.providerid = account.provider_id; + info.set_account(single_info); + } + context_->manifest_plugins_data.get().account_info.set(info); + return true; +} + +bool StepParseManifest::FillShortcuts() { + std::shared_ptr shortcut_info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kShortcutListKey)); + if (!shortcut_info) + return true; + + ShortcutListInfo list; + for (auto& shortcut : shortcut_info->shortcuts) { + ShortcutInfo single_info; + single_info.app_id = shortcut.app_id; + single_info.extra_data = shortcut.extra_data; + single_info.extra_key = shortcut.extra_key; + single_info.icon = shortcut.icon; + single_info.labels = shortcut.labels; + list.push_back(single_info); + } + context_->manifest_plugins_data.get().shortcut_info.set(list); + return true; +} + +template +bool StepParseManifest::FillBackgroundCategoryInfo(application_x* app, + const T& background_category_data_list) { + for (const auto& background_category : background_category_data_list) { + app->background_category = g_list_append( + app->background_category, strdup(background_category.value().c_str())); + } + + return true; +} + +bool StepParseManifest::FillManifestX(manifest_x* manifest) { + if (!FillPackageInfo(manifest)) + return false; + if (!FillInstallationInfo(manifest)) + return false; + if (!FillUIApplication(manifest)) + return false; + if (!FillServiceApplication(manifest)) + return false; + if (!FillWidgetApplication(manifest)) + return false; + if (!FillPrivileges(manifest)) + return false; + if (!FillAccounts()) + return false; + if (!FillShortcuts()) + return false; + return true; +} + +Step::Status StepParseManifest::process() { + if (!LocateConfigFile()) { + // continue if this is recovery, manifest file may never been created + if (manifest_location_ == ManifestLocation::RECOVERY) { + LOG(DEBUG) << "Manifest for recovery not found"; + return Step::Status::OK; + } + LOG(ERROR) << "No manifest file exists"; + return Step::Status::MANIFEST_NOT_FOUND; + } + parser_.reset(new tpk::parse::TPKConfigParser()); + if (!parser_->ParseManifest(path_)) { + LOG(ERROR) << "[Parse] Parse failed. " << parser_->GetErrorMessage(); + return Step::Status::PARSE_ERROR; + } + + // Copy data from ManifestData to InstallerContext + std::shared_ptr info = + std::static_pointer_cast( + parser_->GetManifestData(app_keys::kManifestKey)); + + context_->pkgid.set(info->package()); + context_->pkg_path.set( + context_->root_application_path.get() / context_->pkgid.get()); + + manifest_x* manifest = + static_cast(calloc(1, sizeof(manifest_x))); + + if (!FillManifestX(const_cast(manifest))) { + LOG(ERROR) << "[Parse] Storing manifest_x failed. " + << parser_->GetErrorMessage(); + return Step::Status::PARSE_ERROR; + } + + if (!context_->tep_path.get().empty()) + manifest->tep_name = context_->tep_path.get().c_str(); + + // 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(); + } + + LOG(DEBUG) << "Parsed package id: " << info->package(); + + switch (store_location_) { + case StoreLocation::NORMAL: + context_->manifest_data.set(manifest); + break; + case StoreLocation::BACKUP: + context_->old_manifest_data.set(manifest); + break; + default: + LOG(ERROR) << "Unknown store location for parsed data"; + return Step::Status::ERROR; + } + return Step::Status::OK; +} + +} // namespace parse +} // namespace common_installer diff --git a/src/common/step/step_parse_manifest.h b/src/common/step/step_parse_manifest.h new file mode 100644 index 0000000..749a3a0 --- /dev/null +++ b/src/common/step/step_parse_manifest.h @@ -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. + +#ifndef COMMON_STEP_STEP_PARSE_MANIFEST_H_ +#define COMMON_STEP_STEP_PARSE_MANIFEST_H_ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace common_installer { +namespace parse { + +/** + * @brief The StepParseManifest class + * Used to parse tpk manifest file and store information to context + * + * This step is parameterized according to: + * - where to look for manifest file + * - where to store information from manifest in context structure + * + * Different installation mode will choose different ManifestLocation and + * StoreLocation for its purpose but main goal of this step parsing tpk + * manifest doesn't change. + */ +class StepParseManifest : public common_installer::Step { + public: + enum class ManifestLocation { + PACKAGE, // parse manifest file from unpacking diretory + INSTALLED, // parse manfiest file from current package installation + RECOVERY // parse manifest file from backup location or package location + }; + + enum class StoreLocation { + NORMAL, // store in context as current application information (new) + BACKUP // store in context as old version application information (update) + }; + + explicit StepParseManifest(common_installer::InstallerContext* context, + ManifestLocation manifest_location, StoreLocation store_location); + + Status process() override; + Status clean() override { return Status::OK; } + Status undo() override { return Status::OK; } + Status precheck() override; + + protected: + bool LocateConfigFile(); + boost::filesystem::path path_; + + private: + bool FillInstallationInfo(manifest_x* manifest); + bool FillPackageInfo(manifest_x* manifest); + bool FillAuthorInfo(manifest_x* manifest); + bool FillDescription(manifest_x* manifest); + bool FillPrivileges(manifest_x* manifest); + bool FillWidgetApplication(manifest_x* manifest); + bool FillServiceApplication(manifest_x* manifest); + bool FillUIApplication(manifest_x* manifest); + template + bool FillAppControl(application_x* manifest, const T& app_control_list); + template + bool FillDataControl(application_x* manifest, const T& data_control_list); + template + bool FillApplicationIconPaths(application_x* manifest, + const T& icons_info); + template + bool FillLabel(application_x* manifest, const T& label_list); + template + bool FillMetadata(application_x* manifest, const T& meta_data_list); + bool FillImage(application_x* app, + const tpk::parse::ApplicationImagesInfo& label_list); + bool FillAccounts(); + bool FillShortcuts(); + template + bool FillBackgroundCategoryInfo(application_x* app, + const T& background_category_data_list); + bool FillManifestX(manifest_x* manifest); + + std::unique_ptr parser_; + ManifestLocation manifest_location_; + StoreLocation store_location_; + + SCOPE_LOG_TAG(ParseManifest) +}; + +} // namespace parse +} // namespace common_installer + +#endif // COMMON_STEP_STEP_PARSE_MANIFEST_H_ -- 2.7.4