From d8f318d70fa917d6e0fd24679cb7da63c2b2c4cd Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 31 Jan 2024 14:16:22 +0900 Subject: [PATCH] Fix metadata plugin Support package metadata for metadata plugin. Change-Id: Ic4e8fcb362a4f29f2d39c982a2e3ad9af1c41968 Signed-off-by: Sangyoon Jang --- src/common/plugins/metadata_plugin.cc | 165 ++++++++++++++++++++-------------- src/common/plugins/metadata_plugin.h | 8 ++ 2 files changed, 108 insertions(+), 65 deletions(-) diff --git a/src/common/plugins/metadata_plugin.cc b/src/common/plugins/metadata_plugin.cc index 3cd4148..c11a577 100644 --- a/src/common/plugins/metadata_plugin.cc +++ b/src/common/plugins/metadata_plugin.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include "common/utils/glist_range.h" @@ -28,6 +29,42 @@ void ClearMetadataDetail(gpointer data) { free(meta); } +GList* GetMetadataListForKey(GList* list, const std::string& key) { + // pack all metadata starting with key to list that will + // be sent to the plugin. + // e.g. all http://developer.samsung.com/tizen/metadata/profile/* + // will be packed for http://developer.samsung.com/tizen/metadata/profile + GList* md_list = nullptr; + for (metadata_x* meta : GListRange(list)) { + if (meta->key && meta->value && + std::string(meta->key).find(key) == 0) { + __metadata_t* md = reinterpret_cast<__metadata_t*>( + calloc(1, sizeof(__metadata_t))); + if (!md) { + LOG(ERROR) << "Out of memory"; + g_list_free_full(md_list, &ClearMetadataDetail); + return nullptr; + } + md->key = strdup(meta->key); + if (!md->key) { + LOG(ERROR) << "Out of memory"; + free(md); + g_list_free_full(md_list, &ClearMetadataDetail); + return nullptr; + } + md->value = strdup(meta->value); + if (!md->value) { + LOG(ERROR) << "Out of memory"; + ClearMetadataDetail(md); + g_list_free_full(md_list, &ClearMetadataDetail); + return nullptr; + } + md_list = g_list_append(md_list, md); + } + } + return md_list; +} + } // namespace namespace common_installer { @@ -49,7 +86,7 @@ bool MetadataPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) { return false; } plugin->pkgid = strdup(manifest->package); - plugin->appid = strdup(appid); + plugin->appid = appid ? strdup(appid) : strdup(""); plugin->plugin_type = strdup(plugin_info_.type().c_str()); plugin->plugin_name = strdup(plugin_info_.name().c_str()); if (!plugin->pkgid || !plugin->appid | @@ -87,6 +124,35 @@ std::string MetadataPlugin::GetFunctionName(ActionType action) const { return pos->second; } +bool MetadataPlugin::LoadPluginInfo(manifest_x* manifest) { + if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package, + MetadataPlugin::kType, + plugin_info_.name().c_str(), + [](const char* pkgid, const char* appid, const char*, + const char*, void* user_data) -> int { + auto* set = static_cast*>(user_data); + set->emplace(std::string(pkgid), std::string(appid)); + return PMINFO_R_OK; + }, + &pkg_app_set_) != PMINFO_R_OK) { + LOG(ERROR) << "Failed to get previous execution info"; + return false; + } + return true; +} + +bool MetadataPlugin::ExecutePlugin(const std::string& name, + const char* pkgid, const char* appid, GList* md_list) { + int result = 0; + Exec(name, &result, pkgid, appid, md_list); + if (result) { + LOG(ERROR) << "Function: " << name << " of plugin " + << plugin_info_.path() << " failed"; + return false; + } + return true; +} + bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest, ActionType action_type) { std::string name; @@ -94,58 +160,33 @@ bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest, if (tag.empty()) return false; - std::set appid_list; if (action_type == ActionType::Upgrade) { - if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package, - MetadataPlugin::kType, - plugin_info_.name().c_str(), - [](const char*, const char* appid, const char*, - const char*, void* user_data) -> int { - auto* list = static_cast*>(user_data); - list->emplace(std::string(appid)); - return PMINFO_R_OK; - }, - &appid_list) != PMINFO_R_OK) { - LOG(ERROR) << "Failed to get previous execution info"; + // Load previous execution info. If some element left in pkg_app_set_ + // at the end of this method, it means that the plugin was not executed for + // this pkg or app. (need to invoke PKGMGR_MDPARSER_PLUGIN_REMOVED) + if (!LoadPluginInfo(manifest)) return false; - } } - for (application_x* app : GListRange(manifest->application)) { - // pack all metadata starting with key to list that will - // be sent to the plugin. - // e.g. all http://developer.samsung.com/tizen/metadata/profile/* - // will be packed for http://developer.samsung.com/tizen/metadata/profile - GList* md_list = nullptr; - for (metadata_x* meta : GListRange(app->metadata)) { - const std::string& sub_key_prefix = plugin_info_.name(); - if (meta->key && meta->value && - std::string(meta->key).find(sub_key_prefix) == 0) { - __metadata_t* md = reinterpret_cast<__metadata_t*>( - calloc(1, sizeof(__metadata_t))); - if (!md) { - LOG(ERROR) << "Out of memory"; - g_list_free_full(md_list, &ClearMetadataDetail); - return false; - } - md->key = strdup(meta->key); - if (!md->key) { - LOG(ERROR) << "Out of memory"; - free(md); - g_list_free_full(md_list, &ClearMetadataDetail); - return false; - } - md->value = strdup(meta->value); - if (!md->value) { - LOG(ERROR) << "Out of memory"; - ClearMetadataDetail(md); - g_list_free_full(md_list, &ClearMetadataDetail); - return false; - } - md_list = g_list_append(md_list, md); - } + bool result; + GList* md_list = GetMetadataListForKey(manifest->metadata, + plugin_info_.name()); + if (md_list) { + name = GetFunctionName(action_type); + if (!AddPluginInfo(manifest, nullptr)) { + g_list_free_full(md_list, &ClearMetadataDetail); + return false; } + pkg_app_set_.erase( + std::make_pair(manifest->package, "")); + result = ExecutePlugin(name, manifest->package, nullptr, md_list); + g_list_free_full(md_list, &ClearMetadataDetail); + if (!result) + return false; + } + for (application_x* app : GListRange(manifest->application)) { + md_list = GetMetadataListForKey(app->metadata, plugin_info_.name()); // skip application if it has no given metadata if (!md_list) { continue; @@ -155,32 +196,26 @@ bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest, g_list_free_full(md_list, &ClearMetadataDetail); return false; } - appid_list.erase(app->appid); - } - int result = 0; - Exec(name, &result, manifest->package, app->appid, md_list); - if (result) { - LOG(ERROR) << "Function: " << name << " of plugin " - << plugin_info_.path() << " failed"; - g_list_free_full(md_list, &ClearMetadataDetail); - return false; + pkg_app_set_.erase( + std::make_pair( + manifest->package, app->appid)); } + result = ExecutePlugin(name, manifest->package, app->appid, md_list); g_list_free_full(md_list, &ClearMetadataDetail); + if (!result) + return false; } - if (action_type == ActionType::Clean || - action_type == ActionType::Undo) + if (action_type == ActionType::Clean || action_type == ActionType::Undo) name = GetFunctionName(action_type); else name = GetFunctionName(ActionType::Removed); - for (const auto& appid : appid_list) { - int result = 0; - Exec(name, &result, manifest->package, appid.c_str(), nullptr); - if (result) { - LOG(ERROR) << "Function: " << name << " of plugin " - << plugin_info_.path() << " failed"; + + for (const auto& pkg_app : pkg_app_set_) { + result = ExecutePlugin(name, pkg_app.first.c_str(), + pkg_app.second.empty() ? nullptr : pkg_app.second.c_str(), nullptr); + if (!result) return false; - } } return true; } diff --git a/src/common/plugins/metadata_plugin.h b/src/common/plugins/metadata_plugin.h index 2e004ad..21750da 100644 --- a/src/common/plugins/metadata_plugin.h +++ b/src/common/plugins/metadata_plugin.h @@ -6,7 +6,9 @@ #define COMMON_PLUGINS_METADATA_PLUGIN_H_ #include +#include #include +#include #include "common/plugins/plugin.h" @@ -21,9 +23,15 @@ class MetadataPlugin : public Plugin { ActionType action_type) override; private: + using PkgAppPair = std::pair; + bool LoadPluginInfo(manifest_x* manifest); + bool ExecutePlugin(const std::string& name, const char* pkgid, + const char* appid, GList* md_list); bool AddPluginInfo(manifest_x* manifest, const char* appid); std::string GetFunctionName(ActionType action) const; + std::set pkg_app_set_; + using Plugin::Plugin; SCOPE_LOG_TAG(MetadataPlugin) -- 2.7.4