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>
14 #include "common/utils/glist_range.h"
18 std::string GetMetadataTag(const std::string& url) {
19 return url.substr(url.find_last_of('/') + 1);
22 void ClearMetadataDetail(gpointer data) {
23 __metadata_t* meta = reinterpret_cast<__metadata_t*>(data);
25 free(const_cast<char*>(meta->key));
27 free(const_cast<char*>(meta->value));
33 namespace common_installer {
35 const char MetadataPlugin::kType[] = "metadata";
37 std::unique_ptr<MetadataPlugin> MetadataPlugin::Create(
38 const PluginInfo& plugin_info) {
39 std::unique_ptr<MetadataPlugin> plugin(new MetadataPlugin(plugin_info));
45 bool MetadataPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) {
46 plugin_x* plugin = static_cast<plugin_x*>(calloc(1, sizeof(plugin_x)));
48 LOG(ERROR) << "out of memory";
51 plugin->pkgid = strdup(manifest->package);
52 plugin->appid = strdup(appid);
53 plugin->plugin_type = strdup(plugin_info_.type().c_str());
54 plugin->plugin_name = strdup(plugin_info_.name().c_str());
55 if (!plugin->pkgid || !plugin->appid |
56 !plugin->plugin_type || !plugin->plugin_name) {
57 LOG(ERROR) << "out of memory";
60 free(plugin->plugin_type);
61 free(plugin->plugin_name);
65 manifest->plugin = g_list_append(manifest->plugin, plugin);
69 std::string MetadataPlugin::GetFunctionName(ActionType action) const {
70 static std::map<ActionType, std::string> names {
71 {ActionType::Install, "PKGMGR_MDPARSER_PLUGIN_INSTALL"},
72 {ActionType::Upgrade, "PKGMGR_MDPARSER_PLUGIN_UPGRADE"},
73 {ActionType::Uninstall, "PKGMGR_MDPARSER_PLUGIN_UNINSTALL"},
74 {ActionType::RecoverInstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERINSTALL"},
75 {ActionType::RecoverUpgrade, "PKGMGR_MDPARSER_PLUGIN_RECOVERUPGRADE"},
76 {ActionType::RecoverUninstall, "PKGMGR_MDPARSER_PLUGIN_RECOVERUNINSTALL"},
77 {ActionType::Clean, "PKGMGR_MDPARSER_PLUGIN_CLEAN"},
78 {ActionType::Undo, "PKGMGR_MDPARSER_PLUGIN_UNDO"},
79 {ActionType::Removed, "PKGMGR_MDPARSER_PLUGIN_REMOVED"},
82 auto pos = names.find(action);
83 if (pos == names.end()) {
84 LOG(INFO) << "Function name not defined";
90 bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest,
91 ActionType action_type) {
93 std::string tag = GetMetadataTag(plugin_info_.name());
97 if (action_type == ActionType::Upgrade) {
98 if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package,
99 MetadataPlugin::kType,
100 plugin_info_.name().c_str(),
101 [](const char*, const char* appid, const char*,
102 const char*, void* user_data) -> int {
104 static_cast<std::vector<std::string>*>(user_data);
105 appid_list->emplace_back(std::string(appid));
108 &appid_list_) != PMINFO_R_OK) {
109 LOG(ERROR) << "Failed to get previous execution info";
112 std::sort(appid_list_.begin(), appid_list_.end());
115 for (application_x* app : GListRange<application_x*>(manifest->application)) {
116 // pack all metadata starting with key to list that will
117 // be sent to the plugin.
118 // e.g. all http://developer.samsung.com/tizen/metadata/profile/*
119 // will be packed for http://developer.samsung.com/tizen/metadata/profile
120 GList* md_list = nullptr;
121 for (metadata_x* meta : GListRange<metadata_x*>(app->metadata)) {
122 const std::string& sub_key_prefix = plugin_info_.name();
123 if (meta->key && meta->value &&
124 std::string(meta->key).find(sub_key_prefix) == 0) {
125 __metadata_t* md = reinterpret_cast<__metadata_t*>(
126 calloc(1, sizeof(__metadata_t)));
128 LOG(ERROR) << "Out of memory";
129 g_list_free_full(md_list, &ClearMetadataDetail);
132 md->key = strdup(meta->key);
134 LOG(ERROR) << "Out of memory";
136 g_list_free_full(md_list, &ClearMetadataDetail);
139 md->value = strdup(meta->value);
141 LOG(ERROR) << "Out of memory";
142 ClearMetadataDetail(md);
143 g_list_free_full(md_list, &ClearMetadataDetail);
146 md_list = g_list_append(md_list, md);
150 // skip application if it has no given metadata
154 name = GetFunctionName(action_type);
155 if (!AddPluginInfo(manifest, app->appid)) {
156 g_list_free_full(md_list, &ClearMetadataDetail);
159 auto iter = std::lower_bound(appid_list_.begin(), appid_list_.end(),
161 if (iter != appid_list_.end() && *iter == app->appid)
162 appid_list_.erase(iter);
165 Exec(name, &result, manifest->package, app->appid, md_list);
167 LOG(ERROR) << "Function: " << name << " of plugin "
168 << plugin_info_.path() << " failed";
169 g_list_free_full(md_list, &ClearMetadataDetail);
172 g_list_free_full(md_list, &ClearMetadataDetail);
175 if (action_type == ActionType::Clean ||
176 action_type == ActionType::Undo)
177 name = GetFunctionName(action_type);
179 name = GetFunctionName(ActionType::Removed);
180 for (auto appid : appid_list_) {
182 Exec(name, &result, manifest->package, appid.c_str(), nullptr);
184 LOG(ERROR) << "Function: " << name << " of plugin "
185 << plugin_info_.path() << " failed";
192 } // namespace common_installer