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::vector<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 {
92 static_cast<std::vector<std::string>*>(user_data);
93 list->emplace_back(std::string(appid));
96 &appid_list) != PMINFO_R_OK) {
97 LOG(ERROR) << "Failed to get previous execution info";
100 std::sort(appid_list.begin(), appid_list.end());
103 for (application_x* app : GListRange<application_x*>(manifest->application)) {
104 // pack all categories starting with key to list that will
105 // be sent to the plugin.
106 // e.g. all http://tizen.org/category/antivirus/*
107 // will be packed for http://tizen.org/category/antivirus
108 GList* category_list = nullptr;
109 for (const char* category : GListRange<char*>(app->category)) {
110 const std::string& sub_key_prefix = plugin_info_.name();
111 if (std::string(category).find(sub_key_prefix) == 0) {
112 __category_t* c = reinterpret_cast<__category_t*>(
113 calloc(1, sizeof(__category_t)));
115 LOG(ERROR) << "Out of memory";
116 g_list_free_full(category_list, &ClearCategoryDetail);
119 c->name = strdup(category);
121 LOG(ERROR) << "Out of memory";
123 g_list_free_full(category_list, &ClearCategoryDetail);
126 category_list = g_list_append(category_list, c);
130 // skip application if it has no given category
131 if (!category_list) {
132 if (action_type != ActionType::Upgrade)
134 auto iter = std::lower_bound(appid_list.begin(), appid_list.end(),
136 if (iter != appid_list.end() && *iter == app->appid) {
137 name = GetFunctionName(ActionType::Removed);
138 iter = appid_list.erase(iter);
139 category_list = nullptr;
144 name = GetFunctionName(action_type);
145 if (!AddPluginInfo(manifest, app->appid)) {
146 g_list_free_full(category_list, &ClearCategoryDetail);
149 auto iter = std::lower_bound(appid_list.begin(), appid_list.end(),
151 if (iter != appid_list.end() && *iter == app->appid)
152 appid_list.erase(iter);
155 Exec(name, &result, manifest->package, app->appid, category_list);
157 LOG(ERROR) << "Function: " << name << " of plugin "
158 << plugin_info_.path() << " failed";
159 g_list_free_full(category_list, &ClearCategoryDetail);
162 g_list_free_full(category_list, &ClearCategoryDetail);
165 if (action_type != ActionType::Upgrade)
168 name = GetFunctionName(ActionType::Removed);
169 for (const auto& appid : appid_list) {
171 Exec(name, &result, manifest->package, appid, nullptr);
173 LOG(ERROR) << "Function: " << name << " of plugin "
174 << plugin_info_.path() << " failed";
181 } // namespace common_installer