From 69f89f4169a9a785b152a8668203ecbb0af1f5c4 Mon Sep 17 00:00:00 2001 From: ilho kim Date: Mon, 22 Jul 2019 05:35:02 +0000 Subject: [PATCH 01/16] Revert "Fix smoke test" This reverts commit 1f7868218392268ec8c4b102f0a1c59f2dbc1a58. Change-Id: I0d442b650f0d8eab06e197ec34f7d09164076968 --- src/unit_tests/extensive_smoke_test.cc | 1 - src/unit_tests/smoke_test.cc | 1 - 2 files changed, 2 deletions(-) diff --git a/src/unit_tests/extensive_smoke_test.cc b/src/unit_tests/extensive_smoke_test.cc index e35c2fc..1f0a8ab 100644 --- a/src/unit_tests/extensive_smoke_test.cc +++ b/src/unit_tests/extensive_smoke_test.cc @@ -27,7 +27,6 @@ class SmokeEnvironment : public testing::Environment { backups_ = SetupBackupDirectories(test_user.uid); for (auto& path : backups_) ASSERT_TRUE(BackupPath(path)); - ASSERT_TRUE(InitTestDB(test_user.uid)); } void TearDown() override { ASSERT_TRUE(request_mode_ == ci::RequestMode::GLOBAL || diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index a271059..d61b444 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -32,7 +32,6 @@ class SmokeEnvironment : public testing::Environment { backups_ = SetupBackupDirectories(test_user.uid); for (auto& path : backups_) ASSERT_TRUE(BackupPath(path)); - ASSERT_TRUE(InitTestDB(test_user.uid)); } void TearDown() override { ASSERT_TRUE(request_mode_ == ci::RequestMode::GLOBAL || -- 2.7.4 From a69b3bc9156fef778f46d10a74c3473fdb07f97a Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Mon, 22 Jul 2019 17:44:31 +0900 Subject: [PATCH 02/16] Release version 0.12.6 Changes: - Fix smoke test - Revert "Fix smoke test" Change-Id: I0c5e4dcabfc945a0fe9afdf5a140cf8ab354e6ee 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 7f5f962..210e071 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.5 +Version: 0.12.6 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From f19cad36f96b60e87b523e05941e443da02afb92 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Wed, 31 Jul 2019 15:09:06 +0900 Subject: [PATCH 03/16] Add StepRecoverParserPlugin at Hybrid recovery requests Change-Id: Ib388c8eb4372da646c21a640305f20a57099e462 Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 373a984..5cc6d00 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -333,6 +334,7 @@ void HybridInstaller::RecoverySteps() { ci::configuration::StepParseManifest::StoreLocation::NORMAL); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(); -- 2.7.4 From 796718621600c3b037eae6143554ca86975cfbc7 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Tue, 23 Jul 2019 15:46:51 +0900 Subject: [PATCH 04/16] Add StepPrivilegeCompatibility at some hybrid requests Add missing step for ManifestPartialInstall and ManifestPartialUpdate requests. Change-Id: I53a021953985acaa7a41e6b34a4a76e53f33c8d0 Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 5cc6d00..0084aa9 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -554,6 +554,8 @@ void HybridInstaller::ManifestPartialInstallSteps() { hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); AddStep(true); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep( @@ -583,6 +585,8 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep( ci::configuration::StepParseManifest::ManifestLocation::INSTALLED, ci::configuration::StepParseManifest::StoreLocation::BACKUP); + AddStep( + ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); AddStep(); -- 2.7.4 From 3bdacc87226eeef036f3759cc932d2ae9d108d74 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 25 Jul 2019 14:12:41 +0900 Subject: [PATCH 05/16] Fix wgt, hybrid installer issues - Signature will not be saved on requests listed below : Hybrid - ManifestPartialInstall, ManifestPartialUpdate Wgt - ReadonlyUpdateUninstall, ManifestPartialInstall, ManifestPartialInstall, ManifestPartialUpdate - Change security-related steps from StepUpdateSecurity to StepRegisterSecurity for some install requests to not trying registration on readonly files when partial-rw option has given. Change-Id: Id0ebad383cbfd2dab6539fff2ba85bf2971a287d Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 6 +++--- src/wgt/wgt_installer.cc | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 0084aa9..3444d2c 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -553,7 +553,7 @@ void HybridInstaller::ManifestPartialInstallSteps() { AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); - AddStep(true); + AddStep(false); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); @@ -581,7 +581,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); - AddStep(true); + AddStep(false); AddStep( ci::configuration::StepParseManifest::ManifestLocation::INSTALLED, ci::configuration::StepParseManifest::StoreLocation::BACKUP); @@ -594,7 +594,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); AddStep( ci::security::StepPrivacyPrivilege::ActionType::Update); - AddStep(); + AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); AddStep(); diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc index 32d0539..9a74c7b 100644 --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -590,7 +590,7 @@ void WgtInstaller::ReadonlyUpdateUninstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(true); + AddStep(false); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::WGT); AddStep(); @@ -617,7 +617,7 @@ void WgtInstaller::ManifestPartialInstallSteps() { AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); AddStep(); - AddStep(true); + AddStep(false); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::WGT); AddStep(); @@ -642,7 +642,7 @@ void WgtInstaller::ManifestPartialUpdateSteps() { AddStep( ci::configuration::StepParseManifest::ManifestLocation::INSTALLED, ci::configuration::StepParseManifest::StoreLocation::BACKUP); - AddStep(true); + AddStep(false); AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::WGT); AddStep(); @@ -653,7 +653,7 @@ void WgtInstaller::ManifestPartialUpdateSteps() { ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); AddStep( ci::security::StepPrivacyPrivilege::ActionType::Update); - AddStep(); + AddStep(); AddStep( ci::Plugin::ActionType::Upgrade); AddStep(); -- 2.7.4 From 285d71fc2d83e9bf369564b13ec66976206b5228 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 8 Aug 2019 18:25:23 +0900 Subject: [PATCH 06/16] Add StepMergeTpkPrivilege at ManifestPartialInstall/Update steps Change-Id: I9a169422bfd8375c9f61828b4f63d1a67dbab72c Signed-off-by: Junghyun Yeon --- src/hybrid/hybrid_installer.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 3444d2c..4edd226 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -550,6 +550,7 @@ void HybridInstaller::ManifestPartialInstallSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); + AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); @@ -578,6 +579,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { AddStep(); AddStep( wgt::configuration::StepParse::ConfigLocation::INSTALLED, true); + AddStep(); AddStep( hybrid::configuration::StepMergeTpkConfig::MergeType::OVERWRITE); AddStep(); -- 2.7.4 From 0bd55a6e89f617f1c2f58ec704d024859c5a6225 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Fri, 2 Aug 2019 17:30:43 +0900 Subject: [PATCH 07/16] Add StepWgtPatchIcon at ManifestPartialInstall/Update steps Fix Icon path change after manifest partial install/update Change-Id: I6d8b55e38192a8cb89ac3b7468265d0c7454e092 Signed-off-by: Ilho Kim --- src/hybrid/hybrid_installer.cc | 18 ++++--- src/wgt/step/filesystem/step_wgt_patch_icons.cc | 66 +++++++++++++++++-------- src/wgt/step/filesystem/step_wgt_patch_icons.h | 7 +++ src/wgt/wgt_installer.cc | 18 ++++--- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/hybrid/hybrid_installer.cc b/src/hybrid/hybrid_installer.cc index 4edd226..aaaed4d 100644 --- a/src/hybrid/hybrid_installer.cc +++ b/src/hybrid/hybrid_installer.cc @@ -146,7 +146,7 @@ void HybridInstaller::InstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -205,7 +205,7 @@ void HybridInstaller::UpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -301,7 +301,7 @@ void HybridInstaller::DeltaSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -377,7 +377,7 @@ void HybridInstaller::MountInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -436,7 +436,7 @@ void HybridInstaller::MountUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -480,7 +480,7 @@ void HybridInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -523,7 +523,7 @@ void HybridInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -558,6 +558,7 @@ void HybridInstaller::ManifestPartialInstallSteps() { AddStep( ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); + AddStep(false); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::INSTALL); @@ -591,6 +592,7 @@ void HybridInstaller::ManifestPartialUpdateSteps() { ci::security::StepPrivilegeCompatibility::InternalPrivType::BOTH); AddStep(); AddStep(); + AddStep(false); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); @@ -656,7 +658,7 @@ void HybridInstaller::ReadonlyUpdateInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); diff --git a/src/wgt/step/filesystem/step_wgt_patch_icons.cc b/src/wgt/step/filesystem/step_wgt_patch_icons.cc index b80263a..89c5b35 100644 --- a/src/wgt/step/filesystem/step_wgt_patch_icons.cc +++ b/src/wgt/step/filesystem/step_wgt_patch_icons.cc @@ -17,7 +17,7 @@ namespace { const char kDefaultIconPath[] = "/usr/share/wgt-backend/default.png"; -bool PatchIcon(icon_x* icon, const bf::path& dst_path) { +bool PatchIcon(icon_x* icon, const bf::path& dst_path, bool make_copy) { if (!icon) return false; bs::error_code error; @@ -31,13 +31,19 @@ bool PatchIcon(icon_x* icon, const bf::path& dst_path) { icon_path += icon_text.extension(); else icon_path += ".png"; - - bf::copy_file(icon->text, icon_path, - bf::copy_option::overwrite_if_exists, error); - if (error) { - LOG(ERROR) << "Failed to move icon from " << icon->text << " to " - << icon_path; - return false; + if (make_copy) { + bf::copy_file(icon->text, icon_path, + bf::copy_option::overwrite_if_exists, error); + if (error) { + LOG(ERROR) << "Failed to move icon from " << icon->text << " to " + << icon_path; + return false; + } + } else { + if (!bf::exists(icon_path)) { + LOG(ERROR) << "Can't find icon in " << icon_path; + return false; + } } if (icon->text) free(const_cast(icon->text)); @@ -46,6 +52,34 @@ bool PatchIcon(icon_x* icon, const bf::path& dst_path) { return true; } +bool GenerateDefaultIcon(const bf::path& icon_path, + application_x* app, bool make_copy) { + bs::error_code error; + if (make_copy) { + bf::copy_file(kDefaultIconPath, icon_path, + bf::copy_option::overwrite_if_exists, error); + if (error) { + LOG(ERROR) << "Failed to create default icon for web application"; + return false; + } + } else { + if (!bf::exists(icon_path)) { + LOG(ERROR) << "Can't find icon in " << icon_path; + return false; + } + } + icon_x* icon = reinterpret_cast(calloc(1, sizeof(icon_x))); + if (!icon) { + LOG(ERROR) << "Out of memory"; + return false; + } + icon->text = strdup(icon_path.c_str()); + icon->lang = strdup(DEFAULT_LOCALE); + app->icon = g_list_append(app->icon, icon); + + return true; +} + } // namespace namespace wgt { @@ -63,7 +97,7 @@ common_installer::Step::Status StepWgtPatchIcons::process() { GListRange(context_->manifest_data.get()->icon)) { bf::path icon_path = common_icon_location / context_->manifest_data.get()->mainapp_id; - if (!PatchIcon(icon, icon_path)) + if (!PatchIcon(icon, icon_path, make_copy_)) return Status::ICON_ERROR; } for (application_x* app : @@ -74,7 +108,7 @@ common_installer::Step::Status StepWgtPatchIcons::process() { // edit icon->text and copy icons to common location for (auto& icon : GListRange(app->icon)) { bf::path icon_path = common_icon_location / app->appid; - if (!PatchIcon(icon, icon_path)) + if (!PatchIcon(icon, icon_path, make_copy_)) return Status::ICON_ERROR; } } else { @@ -82,20 +116,10 @@ common_installer::Step::Status StepWgtPatchIcons::process() { // create default icon if there is no icon at all bf::path icon_path = common_icon_location / app->appid; icon_path += ".png"; - bf::copy_file(kDefaultIconPath, icon_path, - bf::copy_option::overwrite_if_exists, error); - if (error) { + if (!GenerateDefaultIcon(icon_path, app, make_copy_)) { LOG(ERROR) << "Failed to create default icon for web application"; return Status::ICON_ERROR; } - icon_x* icon = reinterpret_cast(calloc(1, sizeof(icon_x))); - if (!icon) { - LOG(ERROR) << "Out of memory"; - return Status::ICON_ERROR; - } - icon->text = strdup(icon_path.c_str()); - icon->lang = strdup(DEFAULT_LOCALE); - app->icon = g_list_append(app->icon, icon); } } return Status::OK; diff --git a/src/wgt/step/filesystem/step_wgt_patch_icons.h b/src/wgt/step/filesystem/step_wgt_patch_icons.h index 1f478a5..17c351d 100644 --- a/src/wgt/step/filesystem/step_wgt_patch_icons.h +++ b/src/wgt/step/filesystem/step_wgt_patch_icons.h @@ -7,6 +7,7 @@ #include +#include #include #include @@ -23,12 +24,18 @@ class StepWgtPatchIcons : public common_installer::Step { public: using Step::Step; + StepWgtPatchIcons(common_installer::InstallerContext* context, bool make_copy) + : Step(context), make_copy_(make_copy) {} + Status process() override; Status undo() override { return Status::OK; } Status clean() override { return Status::OK; } Status precheck() override { return Status::OK; } STEP_NAME(WgtPatchIcons) + + private: + bool make_copy_; }; } // namespace filesystem diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc index 9a74c7b..840bd81 100644 --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -152,7 +152,7 @@ void WgtInstaller::InstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -205,7 +205,7 @@ void WgtInstaller::UpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -323,7 +323,7 @@ void WgtInstaller::DeltaSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -392,7 +392,7 @@ void WgtInstaller::MountInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -443,7 +443,7 @@ void WgtInstaller::MountUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -478,7 +478,7 @@ void WgtInstaller::ManifestDirectInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep( @@ -514,7 +514,7 @@ void WgtInstaller::ManifestDirectUpdateSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep( @@ -561,7 +561,7 @@ void WgtInstaller::ReadonlyUpdateInstallSteps() { AddStep(); AddStep(); AddStep(); - AddStep(); + AddStep(true); AddStep(); AddStep(); AddStep(); @@ -622,6 +622,7 @@ void WgtInstaller::ManifestPartialInstallSteps() { ci::security::StepPrivilegeCompatibility::InternalPrivType::WGT); AddStep(); AddStep(); + AddStep(false); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::INSTALL); @@ -648,6 +649,7 @@ void WgtInstaller::ManifestPartialUpdateSteps() { AddStep(); AddStep(); AddStep(); + AddStep(false); AddStep(); AddStep( ci::security::StepRegisterTrustAnchor::RegisterType::UPDATE); -- 2.7.4 From ba4766e388d1a967b834bad536e13706d1ece931 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Fri, 9 Aug 2019 17:16:02 +0900 Subject: [PATCH 08/16] Release version 0.12.7 Changes: - Add StepRecoverParserPlugin at Hybrid recovery requests - Add StepPrivilegeCompatibility at some hybrid requests - Fix wgt, hybrid installer issues - Add StepMergeTpkPrivilege at ManifestPartialInstall/Update steps - Add StepWgtPatchIcon at ManifestPartialInstall/Update steps Change-Id: I7b5983f72991ca2cba0377cce7df112cf99abea5 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 210e071..735f828 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.6 +Version: 0.12.7 Release: 1 Group: Application Framework/Package Management License: Apache-2.0 -- 2.7.4 From 1dedf52a82e3ab5b873d4cecbe4b164db19df3b2 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Fri, 9 Aug 2019 16:06:50 +0900 Subject: [PATCH 09/16] Fix coding rule Change-Id: I9d8b2d03d5829278a5451db42a19393e2137eb0a Signed-off-by: Junghyun Yeon --- src/wgt/step/pkgmgr/step_generate_xml.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/wgt/step/pkgmgr/step_generate_xml.cc b/src/wgt/step/pkgmgr/step_generate_xml.cc index 01a1a95..dc4dc71 100644 --- a/src/wgt/step/pkgmgr/step_generate_xml.cc +++ b/src/wgt/step/pkgmgr/step_generate_xml.cc @@ -103,9 +103,8 @@ bool WriteWidgetApplicationAttributesAndElements( [app](const wgt::parse::AppWidget& widget) { return widget.id == app->appid; }); - if (appwidget == appwidgets.end()) { + if (appwidget == appwidgets.end()) return true; - } // Add extra elements for wgt widget-application if (!appwidget->update_period.empty()) { @@ -359,9 +358,8 @@ common_installer::Step::Status StepGenerateXml::process() { xmlTextWriterSetIndent(writer, 1); Status status = GenerateManifestElement(writer); - if (status != Status::OK) { + if (status != Status::OK) return status; - } xmlTextWriterEndDocument(writer); xmlFreeTextWriter(writer); @@ -386,9 +384,9 @@ common_installer::Step::Status StepGenerateXml::GenerateManifestElement( GenerateAuthor(writer); GenerateDescription(writer); Status status = GenerateApplications(writer); - if (status != Status::OK) { + if (status != Status::OK) return status; - } + GeneratePrivilege(writer); GenerateProvidesAppDefinedPrivilege(writer); GenerateAccount(writer); -- 2.7.4 From 3703c42cff26379a47d15ac625a6bcf3293cd13f Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Wed, 10 Jul 2019 20:13:11 +0900 Subject: [PATCH 10/16] Parse 'addon' element - Requires : https://review.tizen.org/gerrit/#/c/platform/core/appfw/wgt-manifest-handlers/+/209520/ https://review.tizen.org/gerrit/#/c/platform/core/appfw/app-installers/+/210406/ Change-Id: Icd20bf982b0cd7107bbbbaa9ec6d971df000847d Signed-off-by: Junghoon Park --- src/wgt/step/configuration/step_parse.cc | 96 +++++++++++++++++++++----------- src/wgt/step/configuration/step_parse.h | 1 + src/wgt/step/pkgmgr/step_generate_xml.cc | 5 -- src/wgt/wgt_app_query_interface.cc | 13 ++++- 4 files changed, 75 insertions(+), 40 deletions(-) diff --git a/src/wgt/step/configuration/step_parse.cc b/src/wgt/step/configuration/step_parse.cc index ec94a82..9799b3e 100644 --- a/src/wgt/step/configuration/step_parse.cc +++ b/src/wgt/step/configuration/step_parse.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -192,10 +193,8 @@ bool StepParse::FillIconPaths(manifest_x* manifest) { auto app_info = GetManifestDataForKey( app_keys::kTizenApplicationKey); - if (!app_info) { - LOG(ERROR) << "Application info manifest data has not been found."; - return false; - } + if (!app_info.get()) + return true; auto icons_info = GetManifestDataForKey( app_keys::kIconsKey); @@ -273,11 +272,13 @@ bool StepParse::FillWidgetInfo(manifest_x* manifest) { manifest->nodisplay_setting = strdup("false"); manifest->installed_storage = strdup("installed_internal"); - // For wgt package use the long name - application_x* app = - reinterpret_cast(manifest->application->data); - for (auto& item : wgt_info->name_set()) { - AppendLabel(app, item.second, item.first); + if (manifest->application) { + // For wgt package use the long name + application_x* app = + reinterpret_cast(manifest->application->data); + for (auto& item : wgt_info->name_set()) { + AppendLabel(app, item.second, item.first); + } } author_x* author = reinterpret_cast(calloc(1, sizeof(author_x))); @@ -339,10 +340,8 @@ bool StepParse::FillMainApplicationInfo(manifest_x* manifest) { auto app_info = GetManifestDataForKey( app_keys::kTizenApplicationKey); - if (!app_info) { - LOG(ERROR) << "Application info manifest data has not been found."; - return false; - } + if (!app_info.get()) + return true; bool has_watch_category = false; bool has_ime = false; bool has_downloadable_font = false; @@ -432,6 +431,21 @@ bool StepParse::FillMainApplicationInfo(manifest_x* manifest) { return true; } +bool StepParse::FillAddonInfo(manifest_x* manifest) { + auto addon_info = GetManifestDataForKey( + app_keys::kTizenAddonKey); + if (!addon_info) + return true; + + char *pkg = strdup(addon_info->package().c_str()); + if (!pkg) + return false; + + manifest->package = pkg; + + return true; +} + bool StepParse::FillServiceApplicationInfo(manifest_x* manifest) { auto service_list = GetManifestDataForKey( @@ -564,7 +578,6 @@ bool StepParse::FillWidgetApplicationInfo(manifest_x* manifest) { return true; } - bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) { auto manifest_data = parser_->GetManifestData( app_keys::kTizenBackgroundCategoryKey); @@ -575,6 +588,9 @@ bool StepParse::FillBackgroundCategoryInfo(manifest_x* manifest) { if (!bc_list) return true; + if (!manifest->application) + return true; + application_x* app = reinterpret_cast(manifest->application->data); @@ -612,6 +628,9 @@ bool StepParse::FillAppControl(manifest_x* manifest) { GetManifestDataForKey( app_keys::kTizenApplicationAppControlsKey); + if (!manifest->application) + return true; + application_x* app = reinterpret_cast(manifest->application->data); if (app_info_list) { @@ -722,6 +741,9 @@ bool StepParse::FillCategories(manifest_x* manifest) { if (!category_info) return true; + if (!manifest->application) + return true; + application_x* app = reinterpret_cast(manifest->application->data); // there is one app atm @@ -806,6 +828,8 @@ bool StepParse::FillManifestX(manifest_x* manifest) { return false; if (!FillMainApplicationInfo(manifest)) return false; + if (!FillAddonInfo(manifest)) + return false; if (!FillWidgetInfo(manifest)) return false; if (!FillInstallationInfo(manifest)) @@ -898,12 +922,10 @@ common_installer::Step::Status StepParse::process() { } } else { // making backup of content data and services content data - auto content_info = - GetManifestDataForKey( - wgt::application_widget_keys::kTizenContentKey); - auto service_list = - GetManifestDataForKey( - wgt::application_widget_keys::kTizenServiceKey); + auto content_info = GetManifestDataForKey( + app_keys::kTizenContentKey); + auto service_list = GetManifestDataForKey( + app_keys::kTizenServiceKey); if (content_info) backend_data->content.set(*content_info); if (service_list) @@ -911,12 +933,12 @@ common_installer::Step::Status StepParse::process() { } // Copy data from ManifestData to InstallerContext - auto info = - GetManifestDataForKey( - wgt::application_widget_keys::kTizenApplicationKey); - auto wgt_info = - GetManifestDataForKey( - wgt::application_widget_keys::kTizenWidgetKey); + auto info = GetManifestDataForKey( + app_keys::kTizenApplicationKey); + auto wgt_info = GetManifestDataForKey( + app_keys::kTizenWidgetKey); + auto addon_info = GetManifestDataForKey( + app_keys::kTizenAddonKey); std::string name; const auto& name_set = wgt_info->name_set(); @@ -933,7 +955,8 @@ common_installer::Step::Status StepParse::process() { short_name = short_name_set.begin()->second; const std::string& package_version = wgt_info->version(); - const std::string& required_api_version = info->required_version(); + const std::string& required_api_version = addon_info.get() ? + addon_info->required_version() : info->required_version(); manifest_x* manifest = static_cast(calloc(1, sizeof(manifest_x))); @@ -972,14 +995,23 @@ common_installer::Step::Status StepParse::process() { backend_data->settings.set(*settings_info); LOG(DEBUG) << " Read data -[ "; - LOG(DEBUG) << "App id: " << info->id(); - LOG(DEBUG) << " package = " << info->package(); - LOG(DEBUG) << " id = " << info->id(); + if (info.get()) + LOG(DEBUG) << "App id: " << info->id(); + if (info.get()) + LOG(DEBUG) << " package = " << info->package(); + else if (addon_info.get()) + LOG(DEBUG) << " package = " << addon_info->package(); + if (info.get()) + 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(); + if (info.get()) + LOG(DEBUG) << " api_version = " << info->required_version(); + else if (addon_info.get()) + LOG(DEBUG) << " api_version = " << addon_info->required_version(); + if (info.get()) + LOG(DEBUG) << " launch_mode = " << info->launch_mode(); LOG(DEBUG) << " privileges -["; for (const auto& p : permissions) { LOG(DEBUG) << " " << p; diff --git a/src/wgt/step/configuration/step_parse.h b/src/wgt/step/configuration/step_parse.h index e875f77..5c8593c 100644 --- a/src/wgt/step/configuration/step_parse.h +++ b/src/wgt/step/configuration/step_parse.h @@ -59,6 +59,7 @@ class StepParse : public common_installer::Step { bool FillIconPaths(manifest_x* manifest); bool FillWidgetInfo(manifest_x* manifest); bool FillMainApplicationInfo(manifest_x* manifest); + bool FillAddonInfo(manifest_x* manifest); bool FillServiceApplicationInfo(manifest_x* manifest); bool FillWidgetApplicationInfo(manifest_x* manifest); bool FillAppControl(manifest_x* manifest); diff --git a/src/wgt/step/pkgmgr/step_generate_xml.cc b/src/wgt/step/pkgmgr/step_generate_xml.cc index dc4dc71..f6537f9 100644 --- a/src/wgt/step/pkgmgr/step_generate_xml.cc +++ b/src/wgt/step/pkgmgr/step_generate_xml.cc @@ -322,11 +322,6 @@ common_installer::Step::Status StepGenerateXml::precheck() { return Step::Status::PACKAGE_NOT_FOUND; } - if (!context_->manifest_data.get()->application) { - LOG(ERROR) << "No application in package"; - return Step::Status::INVALID_VALUE; - } - return Step::Status::OK; } diff --git a/src/wgt/wgt_app_query_interface.cc b/src/wgt/wgt_app_query_interface.cc index c5abeda..736982c 100644 --- a/src/wgt/wgt_app_query_interface.cc +++ b/src/wgt/wgt_app_query_interface.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,8 @@ std::string WgtAppQueryInterface::GetPkgIdFromPath( return {}; std::vector> handlers = { std::make_shared(), - std::make_shared() + std::make_shared(), + std::make_shared() }; std::unique_ptr registry( new parser::ManifestHandlerRegistry(handlers)); @@ -75,11 +77,16 @@ std::string WgtAppQueryInterface::GetPkgIdFromPath( auto info = std::static_pointer_cast( parser->GetManifestData( wgt::application_widget_keys::kTizenApplicationKey)); - if (!info) { + + auto info_addon = std::static_pointer_cast( + parser->GetManifestData( + wgt::application_widget_keys::kTizenAddonKey)); + + if (!info && !info_addon) { ci::RemoveAll(tmp_path); return {}; } - std::string pkg_id = info->package(); + std::string pkg_id = !info ? info_addon->package() : info->package(); ci::RemoveAll(tmp_path); return pkg_id; -- 2.7.4 From 5301b5ce93f8bfb05b10fb0c2320a751353fee46 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Tue, 20 Aug 2019 10:36:41 +0900 Subject: [PATCH 11/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 12/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 13/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 14/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 15/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 16/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