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 // pack all metadata starting with key to list that will
34 // be sent to the plugin.
35 // e.g. all http://developer.samsung.com/tizen/metadata/profile/*
36 // will be packed for http://developer.samsung.com/tizen/metadata/profile
37 GList* md_list = nullptr;
38 for (metadata_x* meta : GListRange<metadata_x*>(list)) {
39 if (meta->key && meta->value &&
40 std::string(meta->key).find(key) == 0) {
41 __metadata_t* md = reinterpret_cast<__metadata_t*>(
42 calloc(1, sizeof(__metadata_t)));
44 LOG(ERROR) << "Out of memory";
45 g_list_free_full(md_list, &ClearMetadataDetail);
48 md->key = strdup(meta->key);
50 LOG(ERROR) << "Out of memory";
52 g_list_free_full(md_list, &ClearMetadataDetail);
55 md->value = strdup(meta->value);
57 LOG(ERROR) << "Out of memory";
58 ClearMetadataDetail(md);
59 g_list_free_full(md_list, &ClearMetadataDetail);
62 md_list = g_list_append(md_list, md);
70 namespace common_installer {
72 const char MetadataPlugin::kType[] = "metadata";
74 std::unique_ptr<MetadataPlugin> MetadataPlugin::Create(
75 const PluginInfo& plugin_info) {
76 std::unique_ptr<MetadataPlugin> plugin(new MetadataPlugin(plugin_info));
82 bool MetadataPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) {
83 plugin_x* plugin = static_cast<plugin_x*>(calloc(1, sizeof(plugin_x)));
85 LOG(ERROR) << "out of memory";
88 plugin->pkgid = strdup(manifest->package);
89 plugin->appid = appid ? strdup(appid) : strdup("");
90 plugin->plugin_type = strdup(plugin_info_.type().c_str());
91 plugin->plugin_name = strdup(plugin_info_.name().c_str());
92 if (!plugin->pkgid || !plugin->appid |
93 !plugin->plugin_type || !plugin->plugin_name) {
94 LOG(ERROR) << "out of memory";
97 free(plugin->plugin_type);
98 free(plugin->plugin_name);
102 manifest->plugin = g_list_append(manifest->plugin, plugin);
106 std::string MetadataPlugin::GetFunctionName(ActionType action) const {
107 static std::map<ActionType, std::string> names {
108 {ActionType::Install, "PKGMGR_MDPARSER_PLUGIN_INSTALL"},
109 {ActionType::Upgrade, "PKGMGR_MDPARSER_PLUGIN_UPGRADE"},
110 {ActionType::Uninstall, "PKGMGR_MDPARSER_PLUGIN_UNINSTALL"},
111 {ActionType::RecoverInstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERINSTALL"},
112 {ActionType::RecoverUpgrade, "PKGMGR_MDPARSER_PLUGIN_RECOVERUPGRADE"},
113 {ActionType::RecoverUninstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERUNINSTALL"},
114 {ActionType::Clean, "PKGMGR_MDPARSER_PLUGIN_CLEAN"},
115 {ActionType::Undo, "PKGMGR_MDPARSER_PLUGIN_UNDO"},
116 {ActionType::Removed, "PKGMGR_MDPARSER_PLUGIN_REMOVED"},
119 auto pos = names.find(action);
120 if (pos == names.end()) {
121 LOG(INFO) << "Function name not defined";
127 bool MetadataPlugin::LoadPluginInfo(manifest_x* manifest) {
128 if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package,
129 MetadataPlugin::kType,
130 plugin_info_.name().c_str(),
131 [](const char* pkgid, const char* appid, const char*,
132 const char*, void* user_data) -> int {
133 auto* set = static_cast<std::set<PkgAppPair>*>(user_data);
134 set->emplace(std::string(pkgid), std::string(appid));
137 &pkg_app_set_) != PMINFO_R_OK) {
138 LOG(ERROR) << "Failed to get previous execution info";
144 bool MetadataPlugin::ExecutePlugin(const std::string& name,
145 const char* pkgid, const char* appid, GList* md_list) {
147 Exec(name, &result, pkgid, appid, md_list);
149 LOG(ERROR) << "Function: " << name << " of plugin "
150 << plugin_info_.path() << " failed";
156 bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest,
157 ActionType action_type) {
159 std::string tag = GetMetadataTag(plugin_info_.name());
163 if (action_type == ActionType::Upgrade) {
164 // Load previous execution info. If some element left in pkg_app_set_
165 // at the end of this method, it means that the plugin was not executed for
166 // this pkg or app. (need to invoke PKGMGR_MDPARSER_PLUGIN_REMOVED)
167 if (!LoadPluginInfo(manifest))
172 GList* md_list = GetMetadataListForKey(manifest->metadata,
173 plugin_info_.name());
175 name = GetFunctionName(action_type);
176 if (!AddPluginInfo(manifest, nullptr)) {
177 g_list_free_full(md_list, &ClearMetadataDetail);
181 std::make_pair<std::string, std::string>(manifest->package, ""));
182 result = ExecutePlugin(name, manifest->package, nullptr, md_list);
183 g_list_free_full(md_list, &ClearMetadataDetail);
188 for (application_x* app : GListRange<application_x*>(manifest->application)) {
189 md_list = GetMetadataListForKey(app->metadata, plugin_info_.name());
190 // skip application if it has no given metadata
194 name = GetFunctionName(action_type);
195 if (!AddPluginInfo(manifest, app->appid)) {
196 g_list_free_full(md_list, &ClearMetadataDetail);
200 std::make_pair<std::string, std::string>(
201 manifest->package, app->appid));
203 result = ExecutePlugin(name, manifest->package, app->appid, md_list);
204 g_list_free_full(md_list, &ClearMetadataDetail);
209 if (action_type == ActionType::Clean || action_type == ActionType::Undo)
210 name = GetFunctionName(action_type);
212 name = GetFunctionName(ActionType::Removed);
214 for (const auto& pkg_app : pkg_app_set_) {
215 result = ExecutePlugin(name, pkg_app.first.c_str(),
216 pkg_app.second.empty() ? nullptr : pkg_app.second.c_str(), nullptr);
223 } // namespace common_installer