From 5301b5ce93f8bfb05b10fb0c2320a751353fee46 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Tue, 20 Aug 2019 10:36:41 +0900 Subject: [PATCH 01/16] Release version 0.12.8 Changes: - Fix coding rule - Parse 'addon' element Change-Id: I451b302f7ad8c256da80c1e60884363dfadaabd5 Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index 735f828..cc1ed65 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.7 +Version: 0.12.8 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 1aee4f1445cfdb76d7770f2718a9768346799263 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Mon, 26 Aug 2019 14:38:00 +0900 Subject: [PATCH 02/16] Change order of StepRemoveTemporaryDirectory In case installation terminated after StepUnzip, recovery file doesn't have pkgid, and then StepParseManifest will return RECOVERY_DONE, and temporary file doesn't be removed Change-Id: I8102692624a27768c28beb665c851eb3f4d2fd1f Signed-off-by: Ilho Kim --- src/hybrid/hybrid_installer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index aaaed4d..2e0efe3 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -329,10 +329,10 @@ void HybridInstaller::DeltaSteps() { void HybridInstaller::RecoverySteps() { AddStep(pkgmgr_); AddStep(); + AddStep(); AddStep( ci::configuration::StepParseManifest::ManifestLocation::RECOVERY, ci::configuration::StepParseManifest::StoreLocation::NORMAL); - AddStep(); AddStep(); AddStep(); AddStep(); -- 2.7.4 From 81ebf791572ea6ac7a1159f0d0680b130af163b3 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 29 Aug 2019 16:12:25 +0900 Subject: [PATCH 03/16] Release version 0.12.9 Changes: - Change order of StepRemoveTemporaryDirectory Change-Id: Ia8ff88f389b4680247727ff835e9fa6a2d2a34d5 Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index cc1ed65..4c8eb81 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.8 +Version: 0.12.9 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 1de875070177b8ac79f7647d53d60b29699b8411 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 22 Aug 2019 20:57:30 +0900 Subject: [PATCH 04/16] Add recover test for crash after unzip requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/app-installers/+/212535/ Change-Id: I842ef743a815a4ff040c554e1795d3bc5d443b93 Signed-off-by: Ilho Kim --- src/unit_tests/smoke_test.cc | 21 +++++++++++++++++++++ src/unit_tests/smoke_test_helper.cc | 17 ++++++++++++++--- .../smoke/RecoveryMode_CrashAfterUnzip.wgt | Bin 0 -> 38001 bytes 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/unit_tests/test_samples/smoke/RecoveryMode_CrashAfterUnzip.wgt diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index d61b444..4ceba21 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -864,6 +864,27 @@ TEST_F(SmokeTest, InstallExtendedMode) { ASSERT_TRUE(ValidateExtendedPackage(pkgid, {appid}, params)); } +TEST_F(SmokeTest, RecoveryMode_CrashAfterUnzip) { + bf::path path = kSmokePackagesDirectory / "RecoveryMode_CrashAfterUnzip.wgt"; + RemoveAllRecoveryFiles("/wgt-recovery", params.test_user.uid); + ci::Subprocess backend_crash("/usr/bin/wgt-backend-ut/smoke-test-helper"); + std::string test_uid_str = std::to_string(params.test_user.uid); + backend_crash.Run("-i", path.string(), "-u", test_uid_str.c_str(), + "-step_name", "Unzip"); + ASSERT_NE(backend_crash.Wait(), 0); + + std::string pkgid = "smokewgt45"; + bf::path recovery_file = FindRecoveryFile("/wgt-recovery", + params.test_user.uid); + ASSERT_FALSE(recovery_file.empty()); + std::unique_ptr recovery_info = + GetRecoverFileInfo(recovery_file); + ASSERT_TRUE(recovery_info); + ASSERT_EQ(backend.Recover(recovery_file), ci::AppInstaller::Result::OK); + ASSERT_TRUE(CheckPackageNonExistance(pkgid, params)); + ASSERT_FALSE(bf::exists(recovery_info->unpacked_dir())); +} + } // namespace smoke_test int main(int argc, char** argv) { diff --git a/src/unit_tests/smoke_test_helper.cc b/src/unit_tests/smoke_test_helper.cc index 8ddf3df..3549d84 100644 --- a/src/unit_tests/smoke_test_helper.cc +++ b/src/unit_tests/smoke_test_helper.cc @@ -32,14 +32,17 @@ class StepCrash : public ci::Step { wgt::WgtInstaller::STEPS(); \ if (crash_at_ > -1) \ AddStepAtIndex(crash_at_); \ + else if (step_name_.size()) \ + AddStepAfter(step_name_); \ else \ AddStep(); \ } \ class CrashWgtInstaller : public wgt::WgtInstaller { public: - explicit CrashWgtInstaller(ci::PkgMgrPtr pkgmgr, int crash_at) - : wgt::WgtInstaller(pkgmgr), crash_at_(crash_at) { } + explicit CrashWgtInstaller(ci::PkgMgrPtr pkgmgr, int crash_at, + std::string step_name) : wgt::WgtInstaller(pkgmgr), crash_at_(crash_at), + step_name_(step_name) { } private: OVERRIDE_STEPS_BLOCK(InstallSteps) @@ -64,6 +67,7 @@ class CrashWgtInstaller : public wgt::WgtInstaller { OVERRIDE_STEPS_BLOCK(RecoverDBSteps) int crash_at_; + std::string step_name_; }; } // namespace @@ -72,12 +76,19 @@ class CrashWgtInstaller : public wgt::WgtInstaller { int main(int argc, char** argv) { int index = -1; int backend_argc = argc; + std::string step_name; if (!strcmp(argv[argc-2], "-idx")) { index = atoi(argv[argc-1]); backend_argc = argc - 2; LOG(DEBUG) << "Step crash after " << index << " step."; } + if (!strcmp(argv[argc-2], "-step_name")) { + step_name = argv[argc-1]; + backend_argc = argc-2; + LOG(DEBUG) << "Step crash after " << step_name << " step."; + } + ci::PkgmgrInstaller pkgmgr_installer; wgt::WgtAppQueryInterface query_interface; auto pkgmgr = ci::PkgMgrInterface::Create(backend_argc, argv, @@ -87,7 +98,7 @@ int main(int argc, char** argv) { return EINVAL; } - ::CrashWgtInstaller installer(pkgmgr, index); + ::CrashWgtInstaller installer(pkgmgr, index, step_name); return (installer.Run() == ci::AppInstaller::Result::OK) ? 0 : 1; } diff --git a/src/unit_tests/test_samples/smoke/RecoveryMode_CrashAfterUnzip.wgt b/src/unit_tests/test_samples/smoke/RecoveryMode_CrashAfterUnzip.wgt new file mode 100644 index 0000000000000000000000000000000000000000..b9ecec4a6e5436800507c3f79199c30bd97c29a7 GIT binary patch literal 38001 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 HULO4iddX=v literal 0 HcmV?d00001 -- 2.7.4 From ce4b265558925fa44566eed0763ba0b5802c8293 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 4 Sep 2019 15:30:29 +0900 Subject: [PATCH 05/16] Fix static analysis issue Remove unnecessary null checking. Change-Id: I7c86b64e0cfe496c6b361f696b546a7ac7707438 Signed-off-by: Sangyoon Jang --- src/wgt/step/filesystem/step_wgt_patch_icons.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wgt/step/filesystem/step_wgt_patch_icons.cc b/src/wgt/step/filesystem/step_wgt_patch_icons.cc index 89c5b35..1522b1b 100644 --- a/src/wgt/step/filesystem/step_wgt_patch_icons.cc +++ b/src/wgt/step/filesystem/step_wgt_patch_icons.cc @@ -45,8 +45,7 @@ bool PatchIcon(icon_x* icon, const bf::path& dst_path, bool make_copy) { return false; } } - if (icon->text) - free(const_cast(icon->text)); + free(const_cast(icon->text)); icon->text = strdup(icon_path.c_str()); return true; -- 2.7.4 From 6375f258df99df2b71b0c800c3f20da7cb1989d9 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 5 Sep 2019 16:31:36 +0900 Subject: [PATCH 06/16] Release version 0.12.10 Changes: - Add recover test for crash after unzip - Fix static analysis issue Change-Id: I57de64914b46fc66e820100b323c5d5916dd63ef Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index 4c8eb81..7e06255 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.9 +Version: 0.12.10 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 8916816b9b382d4ca878b9a67b5a054bd8eb0a04 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Fri, 9 Aug 2019 17:30:55 +0900 Subject: [PATCH 07/16] Fix StepMergeTpkConfig for application attribute Mainapp attribute should be modified at here to set mainapp as true for webapp. Change-Id: I94aa9e482a2550fefa1378f1fa3e961f0636ad0c Signed-off-by: Junghyun Yeon --- .../step/configuration/step_merge_tpk_config.cc | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/hybrid/step/configuration/step_merge_tpk_config.cc b/src/hybrid/step/configuration/step_merge_tpk_config.cc index d63d003..eb2619f 100644 --- a/src/hybrid/step/configuration/step_merge_tpk_config.cc +++ b/src/hybrid/step/configuration/step_merge_tpk_config.cc @@ -6,6 +6,8 @@ #include +#include + #include "hybrid/hybrid_backend_data.h" namespace hybrid { @@ -22,11 +24,27 @@ common_installer::Step::Status StepMergeTpkConfig::process() { manifest_x* tpk_data = data->tpk_manifest_data.get(); manifest_x* wgt_data = context_->manifest_data.get(); - if (merge_type_ == MergeType::CONCAT) + if (merge_type_ == MergeType::CONCAT) { wgt_data->application = g_list_concat(wgt_data->application, tpk_data->application); - else + } else { + // mainappid should be webapp for hybrid pkg + for (application_x* app : + GListRange(tpk_data->application)) { + if (app->type && strcmp(app->type, "webapp") != 0) + continue; + + if (app->mainapp) + free(app->mainapp); + app->mainapp = strdup("true"); + if (!app->mainapp) { + LOG(ERROR) << "Out of memoery"; + return Status::ERROR; + } + break; + } wgt_data->application = tpk_data->application; + } tpk_data->application = nullptr; return Status::OK; -- 2.7.4 From f815c11aff4bda44a57023bac5adaa021b4a792a Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Fri, 20 Sep 2019 10:38:15 +0900 Subject: [PATCH 08/16] Release version 0.12.11 Changes: - Fix StepMergeTpkConfig for application attribute Change-Id: I99d9ea3a3a30d21a17b1c2ee71e7e7650df4a5f7 Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index 7e06255..e631fab 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.10 +Version: 0.12.11 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 9da7384f9b49669ab861363b73babe2f2ad0d17b Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Tue, 15 Oct 2019 16:02:04 +0900 Subject: [PATCH 09/16] Fix installing privileges of hybrid package Change-Id: Ic8db846e8ffd2b09327f81778036e62c751584be Signed-off-by: Sangyoon Jang --- src/hybrid/hybrid_installer.cc | 58 ++++++++++++++++---------------- src/hybrid/step/pkgmgr/step_merge_xml.cc | 31 +++++++++++++++-- src/hybrid/step/pkgmgr/step_merge_xml.h | 1 + 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 2e0efe3..31028d0 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -132,9 +132,6 @@ void HybridInstaller::InstallSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -155,6 +152,9 @@ void HybridInstaller::InstallSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -185,9 +185,6 @@ void HybridInstaller::UpdateSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -215,6 +212,9 @@ void HybridInstaller::UpdateSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -284,9 +284,6 @@ void HybridInstaller::DeltaSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -311,6 +308,9 @@ void HybridInstaller::DeltaSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep( @@ -363,9 +363,6 @@ void HybridInstaller::MountInstallSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -386,6 +383,9 @@ void HybridInstaller::MountInstallSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -416,9 +416,6 @@ void HybridInstaller::MountUpdateSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -445,6 +442,9 @@ void HybridInstaller::MountUpdateSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -472,9 +472,6 @@ void HybridInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -486,6 +483,9 @@ void HybridInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); @@ -512,9 +512,6 @@ void HybridInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep( @@ -529,6 +526,9 @@ void HybridInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); @@ -550,11 +550,11 @@ void HybridInstaller::ManifestPartialInstallSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); - AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); AddStep(false); + AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); @@ -580,7 +580,6 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); - AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); @@ -588,6 +587,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep( ci::configuration::StepParseManifest::ManifestLocation::INSTALLED, ci::configuration::StepParseManifest::StoreLocation::BACKUP); + AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); @@ -640,9 +640,6 @@ void HybridInstaller::ReadonlyUpdateInstallSteps() { AddStep(); AddStep(); AddStep(true); - AddStep(); - AddStep( - ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -668,6 +665,9 @@ void HybridInstaller::ReadonlyUpdateInstallSteps() { AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); @@ -759,13 +759,13 @@ void HybridInstaller::RecoverDBSteps() { AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); AddStep(); + AddStep(); + AddStep( + hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); - AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); } diff --git a/src/hybrid/step/pkgmgr/step_merge_xml.cc b/src/hybrid/step/pkgmgr/step_merge_xml.cc index 0c87c0d..e36e542 100644 --- a/src/hybrid/step/pkgmgr/step_merge_xml.cc +++ b/src/hybrid/step/pkgmgr/step_merge_xml.cc @@ -32,12 +32,12 @@ const std::vector kBlackListNodes = { {"author"}, {"description"}, {"profile"}, - {"privileges"}, - {"provides-appdefined-privileges"}, {"trust-anchor"}, }; const std::vector kNeedMergeNodes = { {"manifest"}, + {"privileges"}, + {"provides-appdefined-privileges"}, }; const std::vector> kApplicationNodeNames = { {"ui-application", "uiapp"}, @@ -46,6 +46,9 @@ const std::vector> kApplicationNodeNames = { {"watch-application", "watchapp"}, }; +const xmlChar kPrivilegeTypeAttributeKey[] = "type"; +const char kXmlXPrivilegeExpr[] = "//*[local-name()='privilege']"; + } // namespace namespace hybrid { @@ -122,6 +125,27 @@ void StepMergeXml::SetXmlNodeAttribute(xmlNodePtr node, reinterpret_cast(attr_val.c_str())); } +bool StepMergeXml::SetTpkPrivilegeType() { + xmlXPathContextPtr xpath_ctx = xmlXPathNewContext(tpk_doc_); + if (!xpath_ctx) { + LOG(ERROR) << "Failed to create XPath context"; + return false; + } + + xmlXPathObjectPtr xpath_obj = xmlXPathEvalExpression( + (const xmlChar*)kXmlXPrivilegeExpr, xpath_ctx); + if (xpath_obj && !xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) { + for (int i = 0; i < xpath_obj->nodesetval->nodeNr; i++) { + xmlNodePtr node = xpath_obj->nodesetval->nodeTab[i]; + xmlSetProp(node, kPrivilegeTypeAttributeKey, (const xmlChar*)"tpk"); + } + } + + xmlXPathFreeContext(xpath_ctx); + + return true; +} + ci::Step::Status StepMergeXml::process() { bf::path wgt_xml_path = context_->xml_path.get(); bf::path tpk_xml_path = context_->GetPkgPath() / "tizen-manifest.xml"; @@ -129,6 +153,9 @@ ci::Step::Status StepMergeXml::process() { if (!LoadXmlDocument(wgt_xml_path, tpk_xml_path)) return Step::Status::MANIFEST_ERROR; + if (!SetTpkPrivilegeType()) + return Step::Status::MANIFEST_ERROR; + for (auto& entry : kNeedMergeNodes) { xmlNodePtr tpk_node = GetXmlNode(tpk_doc_, entry); if (tpk_node == nullptr) diff --git a/src/hybrid/step/pkgmgr/step_merge_xml.h b/src/hybrid/step/pkgmgr/step_merge_xml.h index 7f75295..a373bcf 100644 --- a/src/hybrid/step/pkgmgr/step_merge_xml.h +++ b/src/hybrid/step/pkgmgr/step_merge_xml.h @@ -34,6 +34,7 @@ class StepMergeXml : public common_installer::Step { void MergeXmlNode(xmlNodePtr node1, xmlNodePtr node2); void SetXmlNodeAttribute(xmlNodePtr node, const std::string& attr, const std::string& attr_val); + bool SetTpkPrivilegeType(); xmlDocPtr wgt_doc_; xmlDocPtr tpk_doc_; -- 2.7.4 From 4c55c3cd441df99406e7c0a5a60e221ad43cdc46 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Tue, 1 Oct 2019 15:54:24 +0900 Subject: [PATCH 10/16] Add StepSetMainapp Add StepSetMainapp for some request types to set mainapp attribute properly. Change-Id: I23717ba8edc9da81ce2c33ddfcd432dcfabcbc29 Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 8 +++++ .../step/configuration/step_merge_tpk_config.cc | 22 ++----------- src/hybrid/step/configuration/step_set_mainapp.cc | 36 ++++++++++++++++++++++ src/hybrid/step/configuration/step_set_mainapp.h | 33 ++++++++++++++++++++ 4 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 src/hybrid/step/configuration/step_set_mainapp.cc create mode 100644 src/hybrid/step/configuration/step_set_mainapp.h diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 31028d0..079754f 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -90,6 +90,7 @@ #include "hybrid/shared_dirs.h" #include "hybrid/step/configuration/step_merge_tpk_config.h" #include "hybrid/step/configuration/step_merge_tpk_privileges.h" +#include "hybrid/step/configuration/step_set_mainapp.h" #include "hybrid/step/configuration/step_stash_tpk_config.h" #include "hybrid/step/encryption/step_encrypt_resources.h" #include "hybrid/step/pkgmgr/step_merge_xml.h" @@ -486,6 +487,7 @@ void HybridInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); + AddStep(); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); @@ -529,6 +531,7 @@ void HybridInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); + AddStep(); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); @@ -552,6 +555,7 @@ void HybridInstaller::ManifestPartialInstallSteps() { wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep(false); AddStep(); @@ -582,6 +586,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep(false); AddStep( @@ -706,6 +711,7 @@ void HybridInstaller::ReadonlyUpdateUninstallSteps() { AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); @@ -766,6 +772,8 @@ void HybridInstaller::RecoverDBSteps() { AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); + AddStep(); + AddStep(); AddStep(); } diff --git a/src/hybrid/step/configuration/step_merge_tpk_config.cc b/src/hybrid/step/configuration/step_merge_tpk_config.cc index eb2619f..d63d003 100644 --- a/src/hybrid/step/configuration/step_merge_tpk_config.cc +++ b/src/hybrid/step/configuration/step_merge_tpk_config.cc @@ -6,8 +6,6 @@ #include -#include - #include "hybrid/hybrid_backend_data.h" namespace hybrid { @@ -24,27 +22,11 @@ common_installer::Step::Status StepMergeTpkConfig::process() { manifest_x* tpk_data = data->tpk_manifest_data.get(); manifest_x* wgt_data = context_->manifest_data.get(); - if (merge_type_ == MergeType::CONCAT) { + if (merge_type_ == MergeType::CONCAT) wgt_data->application = g_list_concat(wgt_data->application, tpk_data->application); - } else { - // mainappid should be webapp for hybrid pkg - for (application_x* app : - GListRange(tpk_data->application)) { - if (app->type && strcmp(app->type, "webapp") != 0) - continue; - - if (app->mainapp) - free(app->mainapp); - app->mainapp = strdup("true"); - if (!app->mainapp) { - LOG(ERROR) << "Out of memoery"; - return Status::ERROR; - } - break; - } + else wgt_data->application = tpk_data->application; - } tpk_data->application = nullptr; return Status::OK; diff --git a/src/hybrid/step/configuration/step_set_mainapp.cc b/src/hybrid/step/configuration/step_set_mainapp.cc new file mode 100644 index 0000000..5d8958d --- /dev/null +++ b/src/hybrid/step/configuration/step_set_mainapp.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2019 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 "hybrid/step/configuration/step_set_mainapp.h" + +#include + +#include + +#include "hybrid/hybrid_backend_data.h" + +namespace hybrid { +namespace configuration { + +common_installer::Step::Status StepSetMainapp::process() { + manifest_x* manifest_data = context_->manifest_data.get(); + for (application_x* app : + GListRange(manifest_data->application)) { + if (app->type && strcmp(app->type, "webapp") != 0) + continue; + + if (app->mainapp) + free(app->mainapp); + app->mainapp = strdup("true"); + if (!app->mainapp) { + LOG(ERROR) << "Out of memoery"; + return Status::ERROR; + } + break; + } + return Status::OK; +} + +} // namespace configuration +} // namespace hybrid diff --git a/src/hybrid/step/configuration/step_set_mainapp.h b/src/hybrid/step/configuration/step_set_mainapp.h new file mode 100644 index 0000000..2b287fb --- /dev/null +++ b/src/hybrid/step/configuration/step_set_mainapp.h @@ -0,0 +1,33 @@ +// Copyright (c) 2019 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 HYBRID_STEP_CONFIGURATION_STEP_SET_MAINAPP_H_ +#define HYBRID_STEP_CONFIGURATION_STEP_SET_MAINAPP_H_ + +#include +#include + +namespace hybrid { +namespace configuration { + +/** + * \brief StepSetMainapp + * Sets main application information + */ +class StepSetMainapp : public common_installer::Step { + public: + using Step::Step; + + Status process() override; + Status clean() override { return Status::OK; } + Status undo() override { return Status::OK; } + Status precheck() override { return Status::OK; } + + STEP_NAME(SetMainapp) +}; + +} // namespace configuration +} // namespace hybrid + +#endif // HYBRID_STEP_CONFIGURATION_STEP_SET_MAINAPP_H_ -- 2.7.4 From e7b478f789b4ddc35e78125f9a50da6eab3269d2 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Mon, 21 Oct 2019 17:31:45 +0900 Subject: [PATCH 11/16] Adjust order of steps Revert from '192eddd5a83d207a760c025c328e3096f8debdca' Change-Id: I81c2d69752e2734d53b15bfe8bb851a9a5014b51 Signed-off-by: Ilho Kim --- src/hybrid/hybrid_installer.cc | 4 ++-- src/wgt/wgt_installer.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 079754f..d25264d 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -239,6 +239,8 @@ void HybridInstaller::UninstallSteps() { AddStep( ci::configuration::StepParseManifest::ManifestLocation::INSTALLED, ci::configuration::StepParseManifest::StoreLocation::NORMAL); + AddStep( + ci::Plugin::ActionType::Uninstall); AddStep(); AddStep(); AddStep(); @@ -254,8 +256,6 @@ void HybridInstaller::UninstallSteps() { ci::security::StepPrivacyPrivilege::ActionType::Uninstall); AddStep(); AddStep(); - AddStep( - ci::Plugin::ActionType::Uninstall); AddStep(); } diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc index 840bd81..2031f14 100644 --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -236,6 +236,8 @@ void WgtInstaller::UninstallSteps() { AddStep(); AddStep(); AddStep(); + AddStep( + ci::Plugin::ActionType::Uninstall); AddStep(); AddStep(); AddStep(); @@ -248,8 +250,6 @@ void WgtInstaller::UninstallSteps() { ci::security::StepPrivacyPrivilege::ActionType::Uninstall); AddStep(); AddStep(); - AddStep( - ci::Plugin::ActionType::Uninstall); AddStep(); } -- 2.7.4 From 463b9e4e09a0b88688b49ff1eccf00baee47b48a Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Tue, 12 Nov 2019 13:28:49 +0900 Subject: [PATCH 12/16] Release version 0.12.12 Changes: - Fix installing privileges of hybrid package - Add StepSetMainapp - Adjust order of steps Change-Id: I5363d57c62a442862fdfb1788b017502117fb9d9 Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index e631fab..71b7e9d 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.11 +Version: 0.12.12 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 8024ea8d1735377be09891f3dd1b5142366a5c4a Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Wed, 13 Nov 2019 14:33:39 +0900 Subject: [PATCH 13/16] Fix ManifestDirectInstall/Update on Hybrid pkg Previous implementation did not consider if modified manifest has deleted. Merging WGT and TPK configs with "OVERWRITE" option will remove WGT application data so fixing it by merge it and to consider modified manifest's existance, CONCAT works as merge, not direct concat to remove duplication. Change-Id: I5ae4f085b0e33dde2a8408fa4a525806e9321b09 Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 33 +++++++------------ .../step/configuration/step_merge_tpk_config.cc | 37 +++++++++++++++------- .../step/configuration/step_merge_tpk_config.h | 11 ------- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index d25264d..fc7824f 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -151,8 +151,7 @@ void HybridInstaller::InstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -211,8 +210,7 @@ void HybridInstaller::UpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -307,8 +305,7 @@ void HybridInstaller::DeltaSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -382,8 +379,7 @@ void HybridInstaller::MountInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -441,8 +437,7 @@ void HybridInstaller::MountUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -482,8 +477,7 @@ void HybridInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -526,8 +520,7 @@ void HybridInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -553,8 +546,7 @@ void HybridInstaller::ManifestPartialInstallSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep(); AddStep(false); @@ -584,8 +576,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep(); AddStep(false); @@ -668,8 +659,7 @@ void HybridInstaller::ReadonlyUpdateInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::CONCAT); + AddStep(); AddStep(); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); @@ -766,8 +756,7 @@ void HybridInstaller::RecoverDBSteps() { wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); AddStep(); AddStep(); - AddStep( - hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); + AddStep(); AddStep(); AddStep(); AddStep( diff --git a/src/hybrid/step/configuration/step_merge_tpk_config.cc b/src/hybrid/step/configuration/step_merge_tpk_config.cc index d63d003..504f557 100644 --- a/src/hybrid/step/configuration/step_merge_tpk_config.cc +++ b/src/hybrid/step/configuration/step_merge_tpk_config.cc @@ -4,31 +4,44 @@ #include "hybrid/step/configuration/step_merge_tpk_config.h" +#include +#include + #include +#include "common/utils/glist_range.h" + #include "hybrid/hybrid_backend_data.h" namespace hybrid { namespace configuration { -StepMergeTpkConfig::StepMergeTpkConfig( - common_installer::InstallerContext* context, - MergeType type) : Step(context), merge_type_(type) { -} - common_installer::Step::Status StepMergeTpkConfig::process() { HybridBackendData* data = static_cast(context_->backend_data.get()); manifest_x* tpk_data = data->tpk_manifest_data.get(); manifest_x* wgt_data = context_->manifest_data.get(); + // FIXME:api-version of tpk app will have wgt's if modified manifest exists. + for (GList* tpk_list = tpk_data->application; + tpk_list != nullptr; tpk_list = g_list_next(tpk_list)) { + application_x* tpk_app = static_cast(tpk_list->data); + bool is_found = false; + for (GList* wgt_list = wgt_data->application; + wgt_list != nullptr; wgt_list = g_list_next(wgt_list)) { + application_x* wgt_app = static_cast(wgt_list->data); + if (!strcmp(tpk_app->appid, wgt_app->appid)) { + is_found = true; + break; + } + } + if (is_found) + continue; + wgt_data->application = g_list_append( + wgt_data->application, tpk_list->data); + tpk_data->application = g_list_delete_link( + tpk_data->application, tpk_list); + } - if (merge_type_ == MergeType::CONCAT) - wgt_data->application = - g_list_concat(wgt_data->application, tpk_data->application); - else - wgt_data->application = tpk_data->application; - - tpk_data->application = nullptr; return Status::OK; } diff --git a/src/hybrid/step/configuration/step_merge_tpk_config.h b/src/hybrid/step/configuration/step_merge_tpk_config.h index 6491d34..2171d59 100644 --- a/src/hybrid/step/configuration/step_merge_tpk_config.h +++ b/src/hybrid/step/configuration/step_merge_tpk_config.h @@ -18,14 +18,6 @@ namespace configuration { */ class StepMergeTpkConfig : public common_installer::Step { public: - enum class MergeType { - CONCAT, // Concatenate configurations - OVERWRITE // Overwrite one with others - }; - - explicit StepMergeTpkConfig(common_installer::InstallerContext* context, - MergeType type); - using Step::Step; Status process() override; @@ -33,9 +25,6 @@ class StepMergeTpkConfig : public common_installer::Step { Status undo() override { return Status::OK; } Status precheck() override { return Status::OK; } - private: - MergeType merge_type_; - STEP_NAME(MergeTpkConfig) }; -- 2.7.4 From c5d864592443afe574c7791de93af8ab1de04772 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 14 Nov 2019 21:01:29 +0900 Subject: [PATCH 14/16] Release version 0.12.13 Changes: - Fix ManifestDirectInstall/Update on Hybrid pkg Change-Id: Idcb2344459d620c6dadda786ac7aa71bf6076543 Signed-off-by: Ilho Kim --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index 71b7e9d..8ddec31 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.12 +Version: 0.12.13 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 82c419c08d2f2be1fa4b42214343c51d3c3e1ba4 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Fri, 22 Nov 2019 11:12:48 +0900 Subject: [PATCH 15/16] Fix static analysis issue Change-Id: I4d81482d873169e2839537dc69f8bac9d6a826cc Signed-off-by: Junghyun Yeon --- src/hybrid/step/configuration/step_merge_tpk_config.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hybrid/step/configuration/step_merge_tpk_config.cc b/src/hybrid/step/configuration/step_merge_tpk_config.cc index 504f557..7caa7b7 100644 --- a/src/hybrid/step/configuration/step_merge_tpk_config.cc +++ b/src/hybrid/step/configuration/step_merge_tpk_config.cc @@ -22,8 +22,9 @@ common_installer::Step::Status StepMergeTpkConfig::process() { manifest_x* tpk_data = data->tpk_manifest_data.get(); manifest_x* wgt_data = context_->manifest_data.get(); // FIXME:api-version of tpk app will have wgt's if modified manifest exists. - for (GList* tpk_list = tpk_data->application; - tpk_list != nullptr; tpk_list = g_list_next(tpk_list)) { + GList* tpk_list = tpk_data->application; + while (tpk_list != nullptr) { + GList *next_list = g_list_next(tpk_list); application_x* tpk_app = static_cast(tpk_list->data); bool is_found = false; for (GList* wgt_list = wgt_data->application; @@ -34,12 +35,16 @@ common_installer::Step::Status StepMergeTpkConfig::process() { break; } } - if (is_found) + if (is_found) { + tpk_list = next_list; continue; + } wgt_data->application = g_list_append( wgt_data->application, tpk_list->data); tpk_data->application = g_list_delete_link( tpk_data->application, tpk_list); + + tpk_list = next_list; } return Status::OK; -- 2.7.4 From 3363d275e172a0c1235a36f7bc30adeca9528ebb Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Fri, 22 Nov 2019 13:25:36 +0900 Subject: [PATCH 16/16] Release version 0.12.14 Changes: - Fix static analysis issue Change-Id: I8489d7691b59361c1a388cde6b105a2795fdc47c Signed-off-by: Junghyun Yeon --- packaging/wgt-backend.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/wgt-backend.spec b/packaging/wgt-backend.spec index 8ddec31..fed4d3f 100644 --- a/packaging/wgt-backend.spec +++ b/packaging/wgt-backend.spec @@ -1,6 +1,6 @@ Name: wgt-backend Summary: Application installer backend for WGT -Version: 0.12.13 +Version: 0.12.14 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4