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/category_plugin.h"
7 #include <pkgmgr-info.h>
8 #include <pkgmgr_parser.h>
14 #include "common/utils/glist_range.h"
18 std::string GetCategoryName(const std::string& url) {
19 return url.substr(url.find_last_of('/') + 1);
22 void ClearCategoryDetail(gpointer data) {
23 __category_t* category = reinterpret_cast<__category_t*>(data);
24 free(const_cast<char*>(category->name));
30 namespace common_installer {
32 const char CategoryPlugin::kType[] = "category";
34 std::unique_ptr<CategoryPlugin> CategoryPlugin::Create(
35 const PluginInfo& plugin_info) {
36 std::unique_ptr<CategoryPlugin> plugin(new CategoryPlugin(plugin_info));
42 bool CategoryPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) {
43 plugin_x* plugin = static_cast<plugin_x*>(calloc(1, sizeof(plugin_x)));
45 LOG(ERROR) << "out of memory";
48 plugin->pkgid = strdup(manifest->package);
49 plugin->appid = strdup(appid);
50 plugin->plugin_type = strdup(plugin_info_.type().c_str());
51 plugin->plugin_name = strdup(plugin_info_.name().c_str());
52 manifest->plugin = g_list_append(manifest->plugin, plugin);
56 std::string CategoryPlugin::GetFunctionName(ActionType action) const {
57 static std::map<ActionType, std::string> names {
58 {ActionType::Install, "PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL"},
59 {ActionType::Upgrade, "PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE"},
60 {ActionType::Uninstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL"},
61 {ActionType::RecoverInstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERINSTALL"}, // NOLINT
62 {ActionType::RecoverUpgrade, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERUPGRADE"}, // NOLINT
63 {ActionType::RecoverUninstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERUNINSTALL"}, // NOLINT
64 {ActionType::Clean, "PKGMGR_CATEGORY_PARSER_PLUGIN_CLEAN"},
65 {ActionType::Undo, "PKGMGR_CATEGORY_PARSER_PLUGIN_UNDO"},
66 {ActionType::Removed, "PKGMGR_CATEGORY_PARSER_PLUGIN_REMOVED"},
69 auto pos = names.find(action);
70 if (pos == names.end()) {
71 LOG(INFO) << "Function name not defined";
77 bool CategoryPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest,
78 ActionType action_type) {
80 std::string tag = GetCategoryName(plugin_info_.name());
84 std::set<std::string> appid_list;
85 if (action_type == ActionType::Upgrade) {
86 if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package,
87 CategoryPlugin::kType,
88 plugin_info_.name().c_str(),
89 [](const char*, const char* appid, const char*,
90 const char*, void* user_data) -> int {
91 auto* list = static_cast<std::set<std::string>*>(user_data);
92 list->emplace(std::string(appid));
95 &appid_list) != PMINFO_R_OK) {
96 LOG(ERROR) << "Failed to get previous execution info";
101 for (application_x* app : GListRange<application_x*>(manifest->application)) {
102 // pack all categories starting with key to list that will
103 // be sent to the plugin.
104 // e.g. all http://tizen.org/category/antivirus/*
105 // will be packed for http://tizen.org/category/antivirus
106 GList* category_list = nullptr;
107 for (const char* category : GListRange<char*>(app->category)) {
108 const std::string& sub_key_prefix = plugin_info_.name();
109 if (std::string(category).find(sub_key_prefix) == 0) {
110 __category_t* c = reinterpret_cast<__category_t*>(
111 calloc(1, sizeof(__category_t)));
113 LOG(ERROR) << "Out of memory";
114 g_list_free_full(category_list, &ClearCategoryDetail);
117 c->name = strdup(category);
119 LOG(ERROR) << "Out of memory";
121 g_list_free_full(category_list, &ClearCategoryDetail);
124 category_list = g_list_append(category_list, c);
128 // skip application if it has no given category
129 if (!category_list) {
130 if (action_type != ActionType::Upgrade)
132 auto iter = appid_list.find(app->appid);
133 if (iter != appid_list.end()) {
134 name = GetFunctionName(ActionType::Removed);
135 appid_list.erase(iter);
136 category_list = nullptr;
141 name = GetFunctionName(action_type);
142 if (!AddPluginInfo(manifest, app->appid)) {
143 g_list_free_full(category_list, &ClearCategoryDetail);
146 appid_list.erase(app->appid);
149 Exec(name, &result, manifest->package, app->appid, category_list);
151 LOG(ERROR) << "Function: " << name << " of plugin "
152 << plugin_info_.path() << " failed";
153 g_list_free_full(category_list, &ClearCategoryDetail);
156 g_list_free_full(category_list, &ClearCategoryDetail);
159 if (action_type != ActionType::Upgrade)
162 name = GetFunctionName(ActionType::Removed);
163 for (const auto& appid : appid_list) {
165 Exec(name, &result, manifest->package, appid, nullptr);
167 LOG(ERROR) << "Function: " << name << " of plugin "
168 << plugin_info_.path() << " failed";
175 } // namespace common_installer