1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/plugins/metadata_plugin.h"
7 #include <pkgmgr-info.h>
8 #include <pkgmgr_parser.h>
15 #include "common/utils/glist_range.h"
19 std::string GetMetadataTag(const std::string& url) {
20 return url.substr(url.find_last_of('/') + 1);
23 void ClearMetadataDetail(gpointer data) {
24 __metadata_t* meta = reinterpret_cast<__metadata_t*>(data);
26 free(const_cast<char*>(meta->key));
28 free(const_cast<char*>(meta->value));
32 GList* GetMetadataListForKey(GList* list, const std::string& key) {
33 GList* md_list = nullptr;
34 for (metadata_x* meta : GListRange<metadata_x*>(list)) {
35 // key and val should not be null (at least empty string)
36 if (!meta->key || !meta->val) {
37 LOG(ERROR) << "Metadata key or val is null";
41 if (std::string(meta->key).find(key) != 0)
44 __metadata_t* md = reinterpret_cast<__metadata_t*>(
45 calloc(1, sizeof(__metadata_t)));
47 LOG(ERROR) << "Out of memory";
48 g_list_free_full(md_list, &ClearMetadataDetail);
51 md->key = strdup(meta->key);
53 LOG(ERROR) << "Out of memory";
55 g_list_free_full(md_list, &ClearMetadataDetail);
58 md->value = strdup(meta->value);
60 LOG(ERROR) << "Out of memory";
61 ClearMetadataDetail(md);
62 g_list_free_full(md_list, &ClearMetadataDetail);
65 md_list = g_list_append(md_list, md);
72 namespace common_installer {
74 const char MetadataPlugin::kType[] = "metadata";
76 std::unique_ptr<MetadataPlugin> MetadataPlugin::Create(
77 const PluginInfo& plugin_info) {
78 std::unique_ptr<MetadataPlugin> plugin(new MetadataPlugin(plugin_info));
84 bool MetadataPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) {
85 plugin_x* plugin = static_cast<plugin_x*>(calloc(1, sizeof(plugin_x)));
87 LOG(ERROR) << "out of memory";
90 plugin->pkgid = strdup(manifest->package);
91 plugin->appid = appid ? strdup(appid) : strdup("");
92 plugin->plugin_type = strdup(plugin_info_.type().c_str());
93 plugin->plugin_name = strdup(plugin_info_.name().c_str());
94 if (!plugin->pkgid || !plugin->appid |
95 !plugin->plugin_type || !plugin->plugin_name) {
96 LOG(ERROR) << "out of memory";
99 free(plugin->plugin_type);
100 free(plugin->plugin_name);
104 manifest->plugin = g_list_append(manifest->plugin, plugin);
108 std::string MetadataPlugin::GetFunctionName(ActionType action) const {
109 static std::map<ActionType, std::string> names {
110 {ActionType::Install, "PKGMGR_MDPARSER_PLUGIN_INSTALL"},
111 {ActionType::Upgrade, "PKGMGR_MDPARSER_PLUGIN_UPGRADE"},
112 {ActionType::Uninstall, "PKGMGR_MDPARSER_PLUGIN_UNINSTALL"},
113 {ActionType::RecoverInstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERINSTALL"},
114 {ActionType::RecoverUpgrade, "PKGMGR_MDPARSER_PLUGIN_RECOVERUPGRADE"},
115 {ActionType::RecoverUninstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERUNINSTALL"},
116 {ActionType::Clean, "PKGMGR_MDPARSER_PLUGIN_CLEAN"},
117 {ActionType::Undo, "PKGMGR_MDPARSER_PLUGIN_UNDO"},
118 {ActionType::Removed, "PKGMGR_MDPARSER_PLUGIN_REMOVED"},
121 auto pos = names.find(action);
122 if (pos == names.end()) {
123 LOG(INFO) << "Function name not defined";
129 bool MetadataPlugin::LoadPluginInfo(manifest_x* manifest) {
130 if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package,
131 MetadataPlugin::kType,
132 plugin_info_.name().c_str(),
133 [](const char* pkgid, const char* appid, const char*,
134 const char*, void* user_data) -> int {
135 auto* set = static_cast<std::set<PkgAppPair>*>(user_data);
136 set->emplace(std::string(pkgid), std::string(appid));
139 &pkg_app_set_) != PMINFO_R_OK) {
140 LOG(ERROR) << "Failed to get previous execution info";
146 bool MetadataPlugin::ExecutePlugin(const std::string& name,
147 const char* pkgid, const char* appid, GList* md_list) {
149 Exec(name, &result, pkgid, appid, md_list);
151 LOG(ERROR) << "Function: " << name << " of plugin "
152 << plugin_info_.path() << " failed";
158 bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest,
159 ActionType action_type) {
161 std::string tag = GetMetadataTag(plugin_info_.name());
165 if (action_type == ActionType::Upgrade) {
166 // Load previous execution info. If some element left in pkg_app_set_
167 // at the end of this method, it means that the plugin was not executed for
168 // this pkg or app. (need to invoke PKGMGR_MDPARSER_PLUGIN_REMOVED)
169 if (!LoadPluginInfo(manifest))
174 // pack all metadata starting with key to list that will
175 // be sent to the plugin.
176 // e.g. all http://developer.samsung.com/tizen/metadata/profile/*
177 // will be packed for http://developer.samsung.com/tizen/metadata/profile
178 GList* md_list = GetMetadataListForKey(manifest->metadata,
179 plugin_info_.name());
181 name = GetFunctionName(action_type);
182 if (!AddPluginInfo(manifest, nullptr)) {
183 g_list_free_full(md_list, &ClearMetadataDetail);
187 std::make_pair<std::string, std::string>(manifest->package, ""));
188 result = ExecutePlugin(name, manifest->package, nullptr, md_list);
189 g_list_free_full(md_list, &ClearMetadataDetail);
194 for (application_x* app : GListRange<application_x*>(manifest->application)) {
195 md_list = GetMetadataListForKey(app->metadata, plugin_info_.name());
196 // skip application if it has no given metadata
200 name = GetFunctionName(action_type);
201 if (!AddPluginInfo(manifest, app->appid)) {
202 g_list_free_full(md_list, &ClearMetadataDetail);
206 std::make_pair<std::string, std::string>(
207 manifest->package, app->appid));
209 result = ExecutePlugin(name, manifest->package, app->appid, md_list);
210 g_list_free_full(md_list, &ClearMetadataDetail);
215 if (action_type == ActionType::Clean || action_type == ActionType::Undo)
216 name = GetFunctionName(action_type);
218 name = GetFunctionName(ActionType::Removed);
220 for (const auto& pkg_app : pkg_app_set_) {
221 result = ExecutePlugin(name, pkg_app.first.c_str(),
222 pkg_app.second.empty() ? nullptr : pkg_app.second.c_str(), nullptr);
229 } // namespace common_installer