From c328ed26c2a6915caf292ecabab498daaf4364df Mon Sep 17 00:00:00 2001 From: Lukasz Wysocki Date: Thu, 29 Oct 2015 11:19:16 +0100 Subject: [PATCH] Add handling for background-category element. This commit depend on: - https://review.tizen.org/gerrit/#/c/50500/ - https://review.tizen.org/gerrit/#/c/52917/ changes should be submitted together. Created sperated header files for classes that belong to ExtraManifestData. Change-Id: Ia487d33b9c83977852a292256499077cf805ee83 --- src/common/installer_context.h | 46 +---- src/common/manifest_info/account.h | 60 ++++++ src/common/step/step_generate_xml.cc | 8 + src/common/utils/specification.h | 188 ++++++++++++++++++ src/wgt/CMakeLists.txt | 1 + src/wgt/step/step_check_background_category.cc | 260 +++++++++++++++++++++++++ src/wgt/step/step_check_background_category.h | 88 +++++++++ src/wgt/step/step_parse.cc | 23 +++ src/wgt/step/step_parse.h | 1 + src/wgt/wgt_installer.cc | 14 +- 10 files changed, 640 insertions(+), 49 deletions(-) create mode 100644 src/common/manifest_info/account.h create mode 100644 src/common/utils/specification.h create mode 100644 src/wgt/step/step_check_background_category.cc create mode 100644 src/wgt/step/step_check_background_category.h diff --git a/src/common/installer_context.h b/src/common/installer_context.h index 6f2cb09..a88779e 100644 --- a/src/common/installer_context.h +++ b/src/common/installer_context.h @@ -23,51 +23,9 @@ #include "common/request.h" #include "common/utils/property.h" -namespace common_installer { - -// TODO(t.iwanek): this structure should be unified for manifest handlers of -// wgt and tpk packages - -/** - * Used to store information about single account - */ -struct SingleAccountInfo { - bool multiple_account_support; - std::vector> names; - std::vector> icon_paths; - std::vector capabilities; - std::string appid; - std::string providerid; -}; - - -/** - * Holds information about all accounts - */ -class AccountInfo { - public: - /** Constructor */ - AccountInfo() {} - /** - * accounts list getter - * - * \return accounts list - */ - const std::vector& accounts() const { - return accounts_; - } +#include "manifest_info/account.h" - /** - * Adds account to the list - * - * \param single_account account to be added - */ - void set_account(const SingleAccountInfo& single_account) { - accounts_.push_back(single_account); - } - private: - std::vector accounts_; -}; +namespace common_installer { // TODO(t.iwanek): this structure should be unified for manifest handlers of // wgt and tpk packages diff --git a/src/common/manifest_info/account.h b/src/common/manifest_info/account.h new file mode 100644 index 0000000..dc4e9c3 --- /dev/null +++ b/src/common/manifest_info/account.h @@ -0,0 +1,60 @@ +// Copyright (c) 2015 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-xwalk file. + +#ifndef COMMON_MANIFEST_INFO_ACCOUNT_H_ +#define COMMON_MANIFEST_INFO_ACCOUNT_H_ + +#include +#include +#include + +namespace common_installer { + +// TODO(t.iwanek): this structure should be unified for manifest handlers of +// wgt and tpk packages + +/** + * \brief Used to store information about single account + */ +struct SingleAccountInfo { + bool multiple_account_support; + std::vector> names; + std::vector> icon_paths; + std::vector capabilities; + std::string appid; + std::string providerid; +}; + + +/** + * \brief Holds information about all accounts + */ +class AccountInfo { + public: + /** \brief Constructor */ + AccountInfo() {} + /** + * \brief Accounts list getter + * + * \return accounts list + */ + const std::vector& accounts() const { + return accounts_; + } + + /** + * \brief Adds account to the list + * + * \param single_account account to be added + */ + void set_account(const SingleAccountInfo& single_account) { + accounts_.push_back(single_account); + } + private: + std::vector accounts_; +}; + +} // namespace common_installer + +#endif // COMMON_MANIFEST_INFO_ACCOUNT_H_ diff --git a/src/common/step/step_generate_xml.cc b/src/common/step/step_generate_xml.cc index d342f78..60f5f8f 100644 --- a/src/common/step/step_generate_xml.cc +++ b/src/common/step/step_generate_xml.cc @@ -170,6 +170,14 @@ common_installer::Step::Status StepGenerateXml::GenerateApplicationCommonXml( xmlTextWriterEndElement(writer); } + for (const char* background_category : GListRange( + app->background_category)) { + xmlTextWriterStartElement(writer, BAD_CAST "background-category"); + xmlTextWriterWriteAttribute(writer, BAD_CAST "value", + BAD_CAST background_category); + xmlTextWriterEndElement(writer); + } + return Step::Status::OK; } diff --git a/src/common/utils/specification.h b/src/common/utils/specification.h new file mode 100644 index 0000000..9cb7c45 --- /dev/null +++ b/src/common/utils/specification.h @@ -0,0 +1,188 @@ +// 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 COMMON_UTILS_SPECIFICATION_H_ +#define COMMON_UTILS_SPECIFICATION_H_ + +#include + +namespace common_installer { + +template +class ISpecification; + +template +using ISpecPtr = std::shared_ptr>; + +/** + * \brief Interface that support chain and nested logical operations + */ +template +class ISpecification { + public: + virtual ~ISpecification() {} + + /** + * \brief Declaration of method that check if condition is meet + * for candidate in order to utilize it's result in + * logical operations AND, OR, and NOT + * + * \param candidate against with test will be performed + * + * \return true if condition is satisfied by candidate, false + * otherwise + */ + virtual bool IsSatisfiedBy(const T &candidate) = 0; + + /** + * \brief Declaration of AND operation, condition has following form + * this AND other + * + * \param other Specification object to allow nested conditions + * + * \return Specification object to allow method chaining. Is expected to + * return AndSpecification implementation. + */ + virtual ISpecPtr And(ISpecPtr other) = 0; + + /** + * \brief Declaration of OR operation, condition has following form + * this OR other + * + * \param other Specification object to allow nested conditions + * + * \return Specification object to allow method chaining. Is expected + * to return OrSpecification implementation. + */ + virtual ISpecPtr Or(ISpecPtr other) = 0; + + /** + * \brief Declaration of Not operation, condition has following form + * !this + * + * \return Specification object to allow method chaining. Is expected + * to return NotSpecification implementation. + */ + virtual ISpecPtr Not() = 0; +}; + +/** + * \brief Abstract class that implement basic logical operations + * AND, OR, and NOT of ISpecification interface. It is expected to + * derive from this class when new specification is needed. Deriving + * class have to implement IsSatifiedBy method. + */ +template +class CompositeSpecification : public ISpecification, + public std::enable_shared_from_this > { + public: + virtual ~CompositeSpecification() {} + + virtual bool IsSatisfiedBy(const T &candidate) = 0; + + /** + * \brief Implementation of AND operation + */ + ISpecPtr And(ISpecPtr other) override; + + /** + * \brief Implementation of OR operation + */ + ISpecPtr Or(ISpecPtr other) override; + + /** + * \brief Implementation of NOT operation + */ + ISpecPtr Not() override; +}; + +/** + * \brief Implementation of AND operation + */ +template +class AndSpecification : public CompositeSpecification { + public: + explicit AndSpecification(ISpecPtr one, ISpecPtr other); + virtual ~AndSpecification() {} + + bool IsSatisfiedBy(const T &candidate) override; + + private: + ISpecPtr one_; + ISpecPtr other_; +}; + +/** + * \brief Implementation of OR operation + */ +template +class OrSpecification : public CompositeSpecification { + public: + explicit OrSpecification(ISpecPtr one, ISpecPtr other); + virtual ~OrSpecification() {} + + bool IsSatisfiedBy(const T &candidate) override; + + private: + ISpecPtr one_; + ISpecPtr other_; +}; + +/** + * \brief Implementation of NOT operation + */ +template +class NotSpecification : public CompositeSpecification { + public: + explicit NotSpecification(ISpecPtr one); + virtual ~NotSpecification() {} + + bool IsSatisfiedBy(const T &candidate) override; + + private: + ISpecPtr wrap_; +}; + +template +ISpecPtr CompositeSpecification::And(ISpecPtr other) { + return std::make_shared>(this->shared_from_this(), other); +} + +template +ISpecPtr CompositeSpecification::Or(ISpecPtr other) { + return std::make_shared>(this->shared_from_this(), other); +} + +template +ISpecPtr CompositeSpecification::Not() { + return std::make_shared>(this->shared_from_this()); +} + +template AndSpecification::AndSpecification( + ISpecPtr one, ISpecPtr other) : one_(one), other_(other) { } + +template bool AndSpecification::IsSatisfiedBy( + const T &candidate) { + return one_->IsSatisfiedBy(candidate) && other_->IsSatisfiedBy(candidate); +} + +template OrSpecification::OrSpecification( + ISpecPtr one, ISpecPtr other) : one_(one), other_(other) { } + +template bool OrSpecification::IsSatisfiedBy( + const T &candidate) { + return one_->IsSatisfiedBy(candidate) || other_->IsSatisfiedBy(candidate); +} + +template NotSpecification::NotSpecification( + ISpecPtr one) : wrap_(one) { } + +template bool NotSpecification::IsSatisfiedBy( + const T &candidate) { + return !wrap_->IsSatisfiedBy(candidate); +} + +} // namespace common_installer + +#endif // COMMON_UTILS_SPECIFICATION_H_ diff --git a/src/wgt/CMakeLists.txt b/src/wgt/CMakeLists.txt index 1b489e5..bd3dc83 100644 --- a/src/wgt/CMakeLists.txt +++ b/src/wgt/CMakeLists.txt @@ -2,6 +2,7 @@ SET(SRCS rds_parser.cc step/step_check_settings_level.cc + step/step_check_background_category.cc step/step_create_symbolic_link.cc step/step_encrypt_resources.cc step/step_parse.cc diff --git a/src/wgt/step/step_check_background_category.cc b/src/wgt/step/step_check_background_category.cc new file mode 100644 index 0000000..ae9142f --- /dev/null +++ b/src/wgt/step/step_check_background_category.cc @@ -0,0 +1,260 @@ +// 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_background_category.h" + +#include +#include +#include +#include + +#include + +#include "common/installer_context.h" +#include "common/utils/glist_range.h" +#include "common/utils/string_util.h" +#include "wgt/wgt_backend_data.h" + +namespace { + +namespace wgt_sec = wgt::security; +using CompositeSpec = + common_installer::CompositeSpecification; + +/** + * \brief Implementation of Specification that check version requirement + */ +class VersionAtLeastSpec : public CompositeSpec { + public: + explicit VersionAtLeastSpec(const utils::VersionNumber version) + : version_(version) {} + + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + return version_ <= candidate.version; + } + + private: + const utils::VersionNumber version_; +}; + +/** + * \brief Implementation of Specification that check certificate level + * requirement + */ +class CertSpec : public CompositeSpec { + public: + explicit CertSpec(common_installer::PrivilegeLevel privilege) : + privilege_(privilege) {} + + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + return candidate.cert == privilege_; + } + + private: + const common_installer::PrivilegeLevel privilege_; +}; + +/** + * \brief Implementation of Specification that check background support + * requirement + */ +class BackgroundSuptSpec : public CompositeSpec { + public: + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + return candidate.background_supt; + } +}; + +/** + * \brief Implementation of Specification that check if any known values + * were parsed in background-category elements + */ +class KnownValueSpec : public CompositeSpec { + public: + explicit KnownValueSpec(const wgt_sec::BackgroundCatSet &values) : + valid_values_(values) { + } + + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + wgt_sec::BackgroundCatSet intersect; + std::set_intersection(valid_values_.begin(), valid_values_.end(), + candidate.values.begin(), candidate.values.end(), + std::inserter(intersect, intersect.begin())); + return !intersect.empty(); + } + + private: + wgt_sec::BackgroundCatSet valid_values_; +}; + +/** + * \brief Implementation of Specification that check if any unknown values + * were parsed in background-category elements + */ +class UnknownValueSpec : public CompositeSpec { + public: + explicit UnknownValueSpec(const wgt_sec::BackgroundCatSet &values) : + invalid_values_(values) { + } + + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + wgt_sec::BackgroundCatSet diff; + std::set_difference(candidate.values.begin(), candidate.values.end(), + invalid_values_.begin(), invalid_values_.end(), + std::inserter(diff, diff.begin())); + return !diff.empty(); + } + + private: + wgt_sec::BackgroundCatSet invalid_values_; +}; + +/** + * \brief Implementation of Specification that check if any of parsed values in + * background-category elements meet requirement of having "system" value + */ +class SystemValueSpec : public CompositeSpec { + public: + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + return candidate.values.find("system") != candidate.values.end(); + } +}; + +/** + * \brief Implementation of Specification that check if no values were parsed + * in background-category elements + */ +class EmptyValueSpec : public CompositeSpec { + public: + bool IsSatisfiedBy(const wgt_sec::BackgroundCatSpecTest &candidate) override { + return candidate.values.empty(); + } +}; + +} // namespace + +namespace wgt { +namespace security { + +StepCheckBackgroundCategory::StepCheckBackgroundCategory( + common_installer::InstallerContext *context) : Step(context), + known_background_categories_ { + "media", "download", "background-network", + "location", "sensor", "iot-communication" }, + not_unknown_background_categories_ { + "media", "download", "background-network", "location", + "sensor", "iot-communication", "system" } { + utils::VersionNumber v24("2.4"); + auto ver24 = std::make_shared(std::move(v24)); + auto certUntrusted = + std::make_shared(common_installer::PrivilegeLevel::UNTRUSTED); + auto certPublic = + std::make_shared(common_installer::PrivilegeLevel::PUBLIC); + auto certParter = + std::make_shared(common_installer::PrivilegeLevel::PARTNER); + auto certPlatform = + std::make_shared(common_installer::PrivilegeLevel::PLATFORM); + auto background_supt = std::make_shared(); + auto known = std::make_shared(known_background_categories_); + auto unknown = + std::make_shared(not_unknown_background_categories_); + auto system = std::make_shared(); + auto empty = std::make_shared(); + + common_installer::ISpecPtr certTrusted = + certParter->Or(certPlatform); + sentAllSpec_ = ver24->Not()->And( + background_supt->And(certPublic->And(system->Not())->Or(certTrusted))); + failSpec_ = certPublic->And(system)->Or(certUntrusted); + systemSpec_ = certTrusted->And(system); + knownSpec_ = failSpec_->Not()->And( + sentAllSpec_->Not())->And(empty->Not())->And(known); + unknownSpec_ = failSpec_->Not()->And(empty->Not())->And(unknown); +} + +GList *StepCheckBackgroundCategory::CopyValuesToBackgroundCategory( + BackgroundCatSet values, GList *backgroundCategories) { + for (auto& background_category : values) { + backgroundCategories = g_list_append( + backgroundCategories, strdup(background_category.c_str())); + } + + return backgroundCategories; +} + +common_installer::Step::Status StepCheckBackgroundCategory::process() { + std::string str_ver(context_->manifest_data.get()->api_version); + common_installer::PrivilegeLevel privilege_level = + context_->privilege_level.get(); + const wgt::parse::SettingInfo& settings = static_cast( + context_->backend_data.get())->settings.get(); + bool bkgnd_supt = settings.background_support_enabled(); + utils::VersionNumber version(str_ver); + + for (application_x* app : + GListRange(context_->manifest_data.get()->application)) { + BackgroundCatSet bkgnd_cat; + + for (const char* background_category : GListRange( + app->background_category)) { + bkgnd_cat.insert(strdup(background_category)); + } + + g_list_free_full(app->background_category, g_free); + app->background_category = nullptr; + + BackgroundCatSpecTest test = + { version, privilege_level, bkgnd_supt, std::move(bkgnd_cat) }; + + if (failSpec_->IsSatisfiedBy(test)) { + LOG(DEBUG) << "Installation fail caused by background-category"; + return Status::ERROR; + } + + if (sentAllSpec_->IsSatisfiedBy(test)) { + app->background_category = CopyValuesToBackgroundCategory( + known_background_categories_, app->background_category); + } + + if (systemSpec_->IsSatisfiedBy(test)) { + app->background_category = g_list_append( + app->background_category, strdup("system")); + } + + if (knownSpec_->IsSatisfiedBy(test)) { + BackgroundCatSet to_insert; + + // Get all known parsed values this is to handle case when more than one + // background-category element is declared and values are mixed + std::set_intersection( + known_background_categories_.begin(), + known_background_categories_.end(), + test.values.begin(), test.values.end(), + std::inserter(to_insert, to_insert.begin())); + + app->background_category = CopyValuesToBackgroundCategory( + to_insert, app->background_category); + } + + if (unknownSpec_->IsSatisfiedBy(test)) { + BackgroundCatSet to_insert; + + // Get all unknown parsed values this is to handle case when more than one + // background-category element is declared and values are mixed + std::set_difference( + test.values.begin(), test.values.end(), + not_unknown_background_categories_.begin(), + not_unknown_background_categories_.end(), + std::inserter(to_insert, to_insert.end())); + + app->background_category = CopyValuesToBackgroundCategory( + to_insert, app->background_category); + } + } + + return Status::OK; +} + +} // namespace security +} // namespace wgt diff --git a/src/wgt/step/step_check_background_category.h b/src/wgt/step/step_check_background_category.h new file mode 100644 index 0000000..2037e92 --- /dev/null +++ b/src/wgt/step/step_check_background_category.h @@ -0,0 +1,88 @@ +// 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_BACKGROUND_CATEGORY_H_ +#define WGT_STEP_STEP_CHECK_BACKGROUND_CATEGORY_H_ + +#include +#include + +#include + +#include "common/step/step.h" +#include "common/utils/logging.h" +#include "common/utils/specification.h" + +namespace wgt { +namespace security { + +typedef std::set BackgroundCatSet; + +struct BackgroundCatSpecTest { + utils::VersionNumber version; + common_installer::PrivilegeLevel cert; + bool background_supt; + BackgroundCatSet values; +}; + +/** + * \brief This step check background category value and modify it depending on + * required version, cert level, background support, and value itself + */ +class StepCheckBackgroundCategory : public common_installer::Step { + public: + using Step::Step; + + explicit StepCheckBackgroundCategory( + common_installer::InstallerContext *context); + + /** + * \brief Check background category values + * + * \return Status::ERROR when "system" 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(CheckBackgroundCategory) + + private: + GList *CopyValuesToBackgroundCategory( + BackgroundCatSet values, GList *backgroundCategories); + + common_installer::ISpecPtr sentAllSpec_; + common_installer::ISpecPtr failSpec_; + common_installer::ISpecPtr systemSpec_; + common_installer::ISpecPtr knownSpec_; + common_installer::ISpecPtr unknownSpec_; + + const BackgroundCatSet known_background_categories_; + const BackgroundCatSet not_unknown_background_categories_; +}; + +} // namespace security +} // namespace wgt + +#endif // WGT_STEP_STEP_CHECK_BACKGROUND_CATEGORY_H_ diff --git a/src/wgt/step/step_parse.cc b/src/wgt/step/step_parse.cc index 48769b0..4f0fafe 100644 --- a/src/wgt/step/step_parse.cc +++ b/src/wgt/step/step_parse.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -245,6 +246,26 @@ bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) { return true; } +bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) { + auto manifest_data = parser_->GetManifestData( + app_keys::kTizenBackgroundCategoryKey); + std::shared_ptr bc_list = + std::static_pointer_cast(manifest_data); + + if (!bc_list) + return true; + + application_x* app = + reinterpret_cast(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 app_info_list = std::static_pointer_cast( @@ -355,6 +376,8 @@ bool StepParse::FillManifestX(manifest_x* manifest) { // so this must execute last if (!FillServiceApplicationInfo(manifest)) return false; + if (!FillBackgroundCategoryInfo(manifest)) + return false; if (!FillExtraManifestInfo(manifest)) return false; return true; diff --git a/src/wgt/step/step_parse.h b/src/wgt/step/step_parse.h index 7b01ff3..4009e49 100644 --- a/src/wgt/step/step_parse.h +++ b/src/wgt/step/step_parse.h @@ -83,6 +83,7 @@ class StepParse : public common_installer::Step { 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 parser_; diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc index b3e53e1..5e29f05 100644 --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -42,19 +42,20 @@ #include "common/step/step_update_security.h" #include "common/step/step_check_old_certificate.h" -#include "wgt/step/step_create_symbolic_link.h" +#include "wgt/step/step_add_default_privileges.h" +#include "wgt/step/step_check_background_category.h" #include "wgt/step/step_check_settings_level.h" +#include "wgt/step/step_create_symbolic_link.h" #include "wgt/step/step_encrypt_resources.h" #include "wgt/step/step_parse.h" #include "wgt/step/step_parse_recovery.h" -#include "wgt/step/step_remove_encryption_data.h" -#include "wgt/step/step_rds_parse.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_copy_storage_directories.h" #include "wgt/step/step_wgt_resource_directory.h" -#include "wgt/step/step_add_default_privileges.h" namespace ci = common_installer; @@ -72,6 +73,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -92,6 +94,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -141,6 +144,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); -- 2.7.4