Fix metadata plugin 99/305299/8
authorSangyoon Jang <jeremy.jang@samsung.com>
Wed, 31 Jan 2024 05:16:22 +0000 (14:16 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Thu, 1 Feb 2024 04:02:40 +0000 (13:02 +0900)
Support package metadata for metadata plugin.

Change-Id: Ic4e8fcb362a4f29f2d39c982a2e3ad9af1c41968
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/common/plugins/metadata_plugin.cc
src/common/plugins/metadata_plugin.h

index 3cd4148..c11a577 100644 (file)
@@ -10,6 +10,7 @@
 #include <algorithm>
 #include <map>
 #include <set>
+#include <utility>
 
 #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<metadata_x*>(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<std::set<PkgAppPair>*>(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<std::string> 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<std::set<std::string>*>(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<application_x*>(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<metadata_x*>(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<std::string, std::string>(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<application_x*>(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<std::string, std::string>(
+              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;
 }
index 2e004ad..21750da 100644 (file)
@@ -6,7 +6,9 @@
 #define COMMON_PLUGINS_METADATA_PLUGIN_H_
 
 #include <memory>
+#include <set>
 #include <string>
+#include <utility>
 
 #include "common/plugins/plugin.h"
 
@@ -21,9 +23,15 @@ class MetadataPlugin : public Plugin {
            ActionType action_type) override;
 
  private:
+  using PkgAppPair = std::pair<std::string, std::string>;
+  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<PkgAppPair> pkg_app_set_;
+
   using Plugin::Plugin;
 
   SCOPE_LOG_TAG(MetadataPlugin)