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));
28 GList* GetCategoryListForKey(GList* list, const std::string& key) {
29 // pack all categories starting with key to list that will
30 // be sent to the plugin.
31 // e.g. all http://tizen.org/category/antivirus/*
32 // will be packed for http://tizen.org/category/antivirus
33 GList* category_list = nullptr;
34 for (const char* category : GListRange<char*>(list)) {
35 if (std::string(category).find(key) != 0)
38 __category_t* c = reinterpret_cast<__category_t*>(
39 calloc(1, sizeof(__category_t)));
41 LOG(ERROR) << "Out of memory";
42 g_list_free_full(category_list, &ClearCategoryDetail);
45 c->name = strdup(category);
47 LOG(ERROR) << "Out of memory";
49 g_list_free_full(category_list, &ClearCategoryDetail);
52 category_list = g_list_append(category_list, c);
59 namespace common_installer {
61 const char CategoryPlugin::kType[] = "category";
63 std::unique_ptr<CategoryPlugin> CategoryPlugin::Create(
64 const PluginInfo& plugin_info) {
65 std::unique_ptr<CategoryPlugin> plugin(new CategoryPlugin(plugin_info));
71 bool CategoryPlugin::AddPluginInfo(manifest_x* manifest, const char* appid) {
72 plugin_x* plugin = static_cast<plugin_x*>(calloc(1, sizeof(plugin_x)));
74 LOG(ERROR) << "out of memory";
77 plugin->pkgid = strdup(manifest->package);
78 plugin->appid = strdup(appid);
79 plugin->plugin_type = strdup(plugin_info_.type().c_str());
80 plugin->plugin_name = strdup(plugin_info_.name().c_str());
81 manifest->plugin = g_list_append(manifest->plugin, plugin);
85 std::string CategoryPlugin::GetFunctionName(ActionType action) const {
86 static std::map<ActionType, std::string> names {
87 {ActionType::Install, "PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL"},
88 {ActionType::Upgrade, "PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE"},
89 {ActionType::Uninstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL"},
90 {ActionType::RecoverInstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERINSTALL"}, // NOLINT
91 {ActionType::RecoverUpgrade, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERUPGRADE"}, // NOLINT
92 {ActionType::RecoverUninstall, "PKGMGR_CATEGORY_PARSER_PLUGIN_RECOVERUNINSTALL"}, // NOLINT
93 {ActionType::Clean, "PKGMGR_CATEGORY_PARSER_PLUGIN_CLEAN"},
94 {ActionType::Undo, "PKGMGR_CATEGORY_PARSER_PLUGIN_UNDO"},
95 {ActionType::Removed, "PKGMGR_CATEGORY_PARSER_PLUGIN_REMOVED"},
98 auto pos = names.find(action);
99 if (pos == names.end()) {
100 LOG(INFO) << "Function name not defined";
106 bool CategoryPlugin::ExecutePlugin(const std::string& name,
107 const char* pkgid, const char* appid, GList* category_list) {
109 Exec(name, &result, pkgid, appid, category_list);
111 LOG(ERROR) << "Function: " << name << " of plugin "
112 << plugin_info_.path() << " failed";
118 bool CategoryPlugin::LoadPluginInfo(manifest_x* manifest) {
119 if (pkgmgrinfo_plugininfo_foreach_plugininfo(manifest->package,
120 CategoryPlugin::kType,
121 plugin_info_.name().c_str(),
122 [](const char*, const char* appid, const char*,
123 const char*, void* user_data) -> int {
124 auto* set = static_cast<std::set<std::string>*>(user_data);
125 set->emplace(std::string(appid));
128 &appid_set_) != PMINFO_R_OK) {
129 LOG(ERROR) << "Failed to get previous execution info";
135 bool CategoryPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest,
136 ActionType action_type) {
138 std::string tag = GetCategoryName(plugin_info_.name());
142 if (action_type == ActionType::Upgrade) {
143 // Load previous execution info. If some element left in appid_set_
144 // at the end of this method, it means that the plugin was not executed for
145 // this app. (need to invoke PKGMGR_MDPARSER_PLUGIN_REMOVED)
146 if (!LoadPluginInfo(manifest))
151 for (application_x* app : GListRange<application_x*>(manifest->application)) {
152 // pack all categories starting with key to list that will
153 // be sent to the plugin.
154 // e.g. all http://tizen.org/category/antivirus/*
155 // will be packed for http://tizen.org/category/antivirus
156 GList* category_list = GetCategoryListForKey(app->category,
157 plugin_info_.name());
158 // skip application if it has no given category
159 if (!category_list) {
162 name = GetFunctionName(action_type);
163 if (!AddPluginInfo(manifest, app->appid)) {
164 g_list_free_full(category_list, &ClearCategoryDetail);
167 appid_set_.erase(app->appid);
170 result = ExecutePlugin(name, manifest->package, app->appid,
172 g_list_free_full(category_list, &ClearCategoryDetail);
177 name = GetFunctionName(ActionType::Removed);
178 for (const auto& appid : appid_set_) {
179 result = ExecutePlugin(name, manifest->package, appid.c_str(), nullptr);
186 } // namespace common_installer